; ; ;NOTE: ---->>>> SYSLIB required to assemble (v2.7B or higher) ; ; ;Remote DIRectory program ; ;rdir.com by simon ewins ; ;--> v1.5+ Updated the program for CP/M Plus compatibility: ; 7-7-84 Added CP/M Plus test and freespace calculation. Added test for ; label, XFCB, and SFCB file entries in the print routine to bypass ; trying to display those entries. George Peace ; ;--> v1.5 added 2400 baud support (2400 is on the way ; in, you know...). Also removed unnecessary global status ; from all labels. S. Kluger ; ;--> v1.4 fixed problem with display of files > 512k, adapted ; for new SDIR module in SYSLIB, defaulted MSPEED to ; 300 baud if speed code is invalid. S. Kluger ; (all changes in lower case) ; ;--> v1.3 added control-c break without using control-s first. ; fixed summary line to make it shorter so that large ; files or disks won't spill over the end of the line. ; ;--> v1.2 adds maximum user and maximum drive to the config table. ; if requested user area or drive is greater than those ; in the table then the current user or drive is taken ; instead. this provides high security as the only way a ; user or drive in excess of the one in the table can be ; accessed is if the user is logged into it! ; ;rdir is a remote directory routine that in addition to the usual ;directory functions will indicate the transfer times for the file ;at each of the 6 most popular baudrates. ; ;the 'switches' at 106h and 107h serve as the default info as well ;as flags for allowing either option. the values of the two locations ;are stuck into place and then if options are allowed they can be ;changed by the /switch. a secure system, obviously would have 106h, ;107h and 10Ah set to 0 as default or 10Ah set to 1 with 117h set to 1 ;to enable options but only if the password is correct. ; ;Patch information: () = setting as distributed ;""""""""""""""""" ; 103h (0) lsb of BSPEED in BYE ; 104h (0) msb of BSPEED in BYE ; 105h (5) baudrate code (see below) if 104h=0000h then this used for speed ; 106h (0) 1=show system files, 0=don't show system files ; 107h (0) 1=show all user areas, 0=show only current user area ; 108h (3) number of columns (2 or 3) ; 109h (21) number of lines on screen -1 ; 10Ah (1) 1=allow options, 0=no options ; 10Bh = default filespec 0??????????? ; 117h (0) 1=passworded option protection, 0=no password ; 118h = 10 character password (right-padded with 0) PASSWORD ; 122h (15) maximum user area allowed ; 123h (2) maximum drive allowed ; ;--->> NOTE: maxusr and maxdrv can ONLY be overcome by being logged to ; a drive/user that is greater than the values at 122h/123h. ; ; ;NOTE: (for those wishing to use this program on a 'local' system) ; ;The baud-rate is gained from reading an address pointed to by the 2 bytes ;at 104H. Set these to the address of BSPEED in BYE. If you aren't running ;BYE and want this to work as a non-remote directory program then set 103H ;& 104H to 0000H and set 105H to one of the following: ; 0 = 110 baud ; 1 = 300 baud ; 2 = 450 baud ; 3 = 600 baud ; 4 = 710 baud ; 5 = 1200 baud ; 6 = 2400 baud ; 7 = 4800 baud ; (by using the /b# option the above rates can be set at runtime) ; ; ;the listing is 3 columns wide and looks like this: ; ;TEST .AQM 3k 3:34 | BYE .COM 3k 3:45 | FILEFIND.COM 6k 6:22 ; ;>> A5: Files: 3 Used: 12k Free: 178k Time: 0:13:30 @ 110bps ; ; ;if 10Ah is set to 1 then the following options are allowed: ; ;RDIR = show all files as determined by bytes 105h -> 109h ;RDIR /b# = show times using bps code #, where # = 0 to 7 above ;RDIR /s = show system files ;RDIR /a = show all user areas ; ;by changing the ambiguous filespec at 10Bh the above will display only ;whatever fits with no filespec entered unless a filespec is entered. ; ;full drive and user and filespecs are supported. ; ;RDIR b4:rcpm-*.l?t /b2 = show files matching on b4: using 600 baud times ;RDIR 5: = show files using defaults on current drive/user 5 ;RDIR B2: /S = show files using defaults, incl. system files ; on drive b:/user 2 ; ;if a filespec is provided then /s is not allowed, /a is still allowed. ; ;the initial password, as distributed, is PASSWORD (all in upper case). ;a non-secure system being used locally would probably have 105h set ;permanently to the user's most frequently used baudrate and 103h/104h ;set to 0000h to disable the search for the bye baudrate code. further, ;the following would allow all options, without a password and show files ;only on the current user area: ;106h = 1 ;107h = 0 ;10Ah = 1 ;117h = 0 ;108h = columns (2 or 3) ;109h = lines (22 as distributed) ; ;forward any comments or suggestions to Simon Ewins at: ; ;Willowdale CBBS (416) 226-9260 ;Toronto EMX RCP/M (416) 484-9663 ;CP/M-NET East (201) 249-0691 ; ;------------------------------------------------------------------------------ ; ;equates: ; CR EQU 13 LF EQU 10 BEL EQU 7 BDOS EQU 5 FCB EQU 5CH FCB2 EQU 6CH DMA EQU 80H CTAIL EQU DMA ; ;start of transient program: rdir.com ; .Z80 CSEG JP START ; ;switches and initial data: ; BSPEED: DW 0000H ;address of baudrate code from BYE BAUDCD: DB 5 ;if bspeed=0000h then this value used for times SYSFIL: DB 0 ;1=show system files, 0=no show system files USRARA: DB 0 ;1=show all user areas, 0=show current area NUMCOL: DB 3 ;number of columns displayed NUMLIN: DB 21 ;number of lines per page OPTION: DB 1 ;1=allow options, 0=not allowed DEFSPC: DB 0,'???????????' ;default file spec PASSON: DB 0 ;1=ask password if option=1, 0=no password PASSWD: DB 'PASSWORD',0,0 ;10 character password if passon=1 MAXUSR: DB 15 ;maximum allowed user area MAXDRV: DB 2 ;maximum allowed drive ; ;set up local stack ; START: LD HL,0 ADD HL,SP LD (CCPSTK),HL ;save stack LD SP,STACK ;start local stack CALL RETUD## LD A,B LD (CURDRV),A LD (OLDDRV),A LD A,C LD (CURUSR),A LD (OLDUSR),A CALL PUTUD## ;save current disk/user JP START0 ;go get command line ; ;exit back to ccp control ; EXIT: CALL GETUD## ;get original disk/user LD HL,(CCPSTK) ;get old stack pointer LD SP,HL ;place it in position RET ;go to it ; ;local stack ; CCPSTK: DS 2 ;ccp stack DB '(c)1984 Simon J. Ewins, ' DB 'all rights reserved...' DS 100 ;stack area STACK: DS 2 ;start of stack ; ;set flags based on default info... may be changed by use of /options ;as required and relative to base flags above. ; START0: LD A,(SYSFIL) LD (SYSOPT),A ;set system shown or not LD A,(USRARA) LD (USROPT),A ;set show all user areas or not LD HL,(BSPEED) ;get address of baudrate code LD A,H OR L ;if address is zero then use BAUDCD as is JR Z,GETCOM LD A,(HL) ;get speed code cp 7 ;valid code? jr c,spok ;yes, skip... ld a,1 ;...else default to 300 spok: LD (BAUDCD),A ;store it in place ; ;get command line info, see if anything entered at all first ; GETCOM: LD HL,CTAIL LD A,(HL) ;get character count OR A JP Z,DODIR ;nothing entered so do default directory INC HL ;point to first character entered PUSH HL ;save it ADD A,L ;point at one passed end of string entered LD L,A XOR A LD (HL),A ;set 0 to mark end POP HL ;get back first character DEC HL ;ready for next inc ; ;determine if filespec entered or just option switch, help, or junk ; GETLOP: INC HL ;point to next character LD A,(HL) OR A ;at end of entry? JP Z,HELP ;not filespec or options so show how to use CP '?' JP Z,HELP ;wants help CP '/' JP Z,DOOPT ;just options so process them CP ' ' JR Z,GETLOP ;get passed any leading spaces ; ;got filespec so initialize fcb ; LD A,1 LD (SPCFLG),A ;flag that we need to move filespec LD DE,FCB CALL FNAME## ;set filespec to fcb JP Z,HELP ;user or drive not legal PUSH HL ;save pointer to next character in string LD A,B CP 0FFH JR Z,GETDRV LD D,A ;move to d to check .... LD A,(MAXDRV) ;.... max drive against requested drive CP D JR C,GETDRV ;too high LD A,D ;okay so get back request DEC A ;adjust drive spec LD (CURDRV),A ;save it JR CHKUSR GETDRV: LD A,(OLDDRV) LD (CURDRV),A ;make it current drive CHKUSR: LD A,C CP 0FFH JR Z,GETUSR LD B,A ;move to b to check .... LD A,(MAXUSR) ;.... max user against requested area CP B JR C,GETUSR ;requested is greater than that allowed LD A,B ;okay user so get back wanted area LD (CURUSR),A JR LOGIN GETUSR: LD A,(OLDUSR) LD (CURUSR),A ;make it current user LOGIN: LD A,(CURDRV) LD B,A LD A,(CURUSR) LD C,A CALL LOGUD## ;log in drive and user (either new or current) ; POP HL ;get pointer to next character LD A,(HL) OR A ;terminated ? JP Z,DODIR ;yes, so done with command line INC HL LD A,(HL) CP '/' JR Z,DOOPT JP DODIR ;no options so do directory ; SIZE: DB 16 CCNT: DS 1 LINE: DS 17 ;input buffer ; DOOPT: INC HL ;point to first character after / PUSH HL ;save pointer to options LD A,(OPTION) ;options allowed? OR A JP Z,DODIR ;0=no LD A,(PASSON) ;need password check? OR A JP Z,NOPASS ;0=no CALL PRINT## DB CR,LF DB 'Password: ',0 XOR A LD HL,SIZE CALL BLINE## LD DE,PASSWD PMATCH: LD A,(DE) OR A JR Z,ENDSTR CP (HL) ;match? JP NZ,EXIT ;nope INC DE INC HL JR PMATCH ENDSTR: LD A,(HL) ;see if also at end of passwd string OR A JP NZ,EXIT ;end of input string before end of passwd CALL CRLF## ; NOPASS: POP HL ;get pointer to option(s) OPTLOP: LD A,(HL) OR A JP Z,DODIR ;no more so do directory listing CP 'S' JR Z,SETSYS CP 'A' JR Z,SETALL CP 'B' JR Z,SETBPS OPTRET: INC HL JR OPTLOP ;keep getting options ; SETSYS: LD A,1 LD (SYSOPT),A ;set flag JR OPTRET ; SETALL: LD A,1 LD (USROPT),A ;set flag JR OPTRET ; SETBPS: INC HL ;point to number LD A,(HL) OR A JR Z,DODIR ;at end of string so go do it CP '0' JR C,OPTRET ;must be valid number 0-6 CP '6'+1 JR NC,OPTRET SUB 30H ;make it binary LD (BAUDCD),A ;store it XOR A ;set BSPEED address to 0 LD (BSPEED),A LD (BSPEED+1),A JR OPTRET ; OLDDRV: ;initial drive DB 0 OLDUSR: ;initial user DB 0 CURDRV: ;working drive DB 0 CURUSR: ;working user DB 0 SELBYT: ;byte to determine files to select DB 0 SPCFLG: ;whether to load fn.ft into defspc DB 0 FSIZ: ;total file size DW 0 FREE: ;free space left DW 0 FILES: ;number of files scanned DW 0 COLCNT: ;current column number DB 0 LINCNT: ;current line number DB 0 RECCNT: ;number of records in current file DW 0 MINS: ;xmodem minutes DB 0 SECS: ;xmodem seconds DB 0 TMINS: ;accumulated time in minutes DW 0 TSECS: ;accumulated time in seconds DW 0 FMASK: ;mask for file display DB ' . ',0 SPACER: ;divider for columns DB 'k',0 FENCE: DB ' | ',0 BTAB: DB 5,13,20,25,29,48,96,0 RECTAB: DB 192,74,48,38,32,20,10,0 BPSTAB: DB '110 ',0 DB '300 ',0 DB '450 ',0 DB '600 ',0 DB '710 ',0 DB '1200',0 db '2400',0 ; ;do directory load, sort and print using values placed in code for ;structuring the directory listing. ; DODIR: LD IY,SELBYT ;point to bit-mapped selection byte LD A,(SPCFLG) ;need to move fcb? OR A JR Z,SYSOPT-1 ;no move LD DE,DEFSPC LD HL,FCB LD BC,12 LDIR ; SYSOPT EQU $+1 ;in-code modification LD A,0 OR A JR Z,NOSYS SET 6,(IY) SET 7,(IY) JR USROPT-1 NOSYS: SET 7,(IY) RES 6,(IY) ; USROPT EQU $+1 ;in-code modification LD A,0 OR A JR Z,USRCUR SET 5,(IY) RES 4,(IY) RES 3,(IY) RES 2,(IY) RES 1,(IY) RES 0,(IY) LD A,(IY) JR GETDIR USRCUR: RES 5,(IY) LD A,(CURUSR) AND 0FH ;clear out top 4 bits ADD A,(IY) ;a=selection bits ; GETDIR: PUSH AF ;save bit map CALL CODEND## ;get end of code LD DE,DEFSPC ;point to filespec POP AF ;get back bit map CALL DIRFS## ;read directory with sizing ; LD (FILES),BC ;save number files selected ; ; Calculate # of K free on selected drive now so that the FREE figure ; will not reflect either the creation or additions to the SD.DIR file ; (which we would probably erase or move anyway). ; PUSH AF PUSH BC PUSH HL LD C,12 ;CP/M version number CALL BDOS LD A,L ;get version CP 30H ;3.0? JP C,FREE20 ;use old method if not LD A,(CURDRV) ;get drive # LD E,A ;use new Compute Free Space BDOS call LD C,46 CALL BDOS LD C,3 ;answer is a 24-bit integer ; FRE3L1: LD HL,82H ;answer is in 1st 3 bytes of DMA adr LD B,3 ;convert it from sectors to K OR A ;by dividing by 8 ; FRE3L2: LD A,M RRA LD M,A DEC HL DEC B JP NZ,FRE3L2 ;loop for 3 bytes DEC C JP NZ,FRE3L1 ;shift 3 times LD HL,(80H) ;now get result in K LD (FREE),HL POP HL POP BC POP AF JP GOTFRE ; FREE20: POP HL POP BC POP AF ; ; CALL DFREE## ;get free space LD (FREE),DE ;save free space in k bytes ; GOTFRE: LD A,B OR C ;if no files then .... JP Z,NOFILE ; ;print each name, size and time ; PRNTF: CALL CRLF## LD A,(NUMCOL) INC A ;offset for base 1 LD (COLCNT),A ;column count to storage LD A,(NUMLIN) INC A ;offset for base 1 LD (LINCNT),A ;line count to storage LD BC,(FILES) ;get number of files loaded INC BC ;base 1 PUSH BC ;save it ; ;loop here for number of files now in bc ; PRTLOP: POP BC DEC BC ;knock down counter LD A,B OR C JP Z,PLOPDN ;0=done PUSH BC PUSH HL ;save current file pointer ; ;check for special CP/M Plus directory entry, if so, bypass it ; LD A,M ;get drive/user byte CP 16 ;label, XFCB, or SFCB? (special=drive+16 JP C,PRTLP1 ;no, continue with file display LD BC,(FILES) ;retrieve number of files selected DEC BC ;drop the count by one LD (FILES),BC ;replace the adjusted file count JP BMPPTR ;don't display this file PRTLP1: ; ;see if user wants to pause ; CALL CONDIN## ;see if character at keyboard CP 'C'-40H ;quit?? JP Z,EXIT ;quit CP 'S'-40H ;pause? CALL Z,WAIT ;pause ; ;see if time for a new line ; LD A,(COLCNT) DEC A ;columns - 1 LD (COLCNT),A OR A CALL Z,NEWLIN ;need new line ; ;print file name ; POP HL ;get pointer back PUSH HL ;save it again INC HL ;point past drive/user byte LD DE,FMASK ;point to print mask LD BC,8 LDIR INC DE LD BC,3 LDIR ;move filename.typ to mask LD HL,FMASK ;point to string CALL PSTR## ;print it ; ;get size of file and print it ; POP HL ;get pointer PUSH HL ;store it again CALL FSIZE## ;get size LD HL,(FSIZ) ;get total size so far ADD HL,DE ;add new file LD (FSIZ),HL ;store result CALL PTFMT ;show result LD HL,SPACER ;point to fence stuff CALL PSTR## ;print it ; ;calculate number of records in file ; POP HL PUSH HL ;point to first byte of record LD DE,12 ;offset to # extents used ADD HL,DE PUSH HL LD A,(HL) LD HL,128 ;multiply by 128 LD H,L ;move to h first CALL MULHA LD (RECCNT),HL ;save partial result POP HL ;pointer to byte 13 INC HL ;... to 14 INC HL ;... to 15 push hl ld a,(hl) ;check S1 byte or a jr z,novfl ;no overflow extents ld hl,0 ld de,4096 ;4096 sectors per ov extent lp: add hl,de dec a jr nz,lp ld de,(reccnt) add hl,de ld (reccnt),hl novfl: pop hl INC HL ;point to records in last extent LD A,(HL) LD E,A LD D,0 LD HL,(RECCNT) ;get partial result ADD HL,DE ;merge to get total records LD (RECCNT),HL ;store it ; ;calculate minutes to send ; LD A,(BAUDCD) ;get baudrate code LD D,0 LD E,A ;table offset LD HL,BTAB ADD HL,DE LD A,(HL) ;factor in a LD HL,(RECCNT) CALL DIVHA ;divide recs/min PUSH HL LD A,L LD (MINS),A ;save minutes ; ;total minutes so far ; LD HL,(TMINS) ;get total so far LD D,0 LD E,A ADD HL,DE LD (TMINS),HL ;total minutes so far ; ;calculate seconds ; LD HL,RECTAB LD D,0 LD A,(BAUDCD) LD E,A ADD HL,DE LD A,(HL) POP HL ;get back remainder CALL MULHA ;h*a CALL SHFTHL CALL SHFTHL CALL SHFTHL CALL SHFTHL LD A,L LD (SECS),A ;save seconds ; ;total seconds so far ; LD HL,(TSECS) ;get total so far LD D,0 LD E,A ADD HL,DE LD (TSECS),HL ;total seconds so far ; ;now show transfer time ; LD A,(MINS) LD D,0 LD E,A CALL PTFMT LD A,':' CALL COUT## LD A,(SECS) LD D,0 LD E,A CALL PTFMT2 ; ;if at last column, don't print fence ; LD A,(COLCNT) CP 1 JR Z,BMPPTR LD HL,FENCE CALL PSTR## ; ;now bump to next filename ; BMPPTR: LD DE,16 POP HL ;get pointer to current file ADD HL,DE JP PRTLOP ; ;done with files so print footer ; PLOPDN: CALL CRLF## CALL CRLF## ; ;current drive ; LD A,(CURDRV) ADD A,41H ;make drive a letter CALL COUT## ;print it ; ;current user area ; LD A,(CURUSR) LD H,0 LD L,A CALL PB2ASC ;print user number LD HL,USRMSG CALL PSTR## ; ;number of files ; LD HL,(FILES) CALL PB2ASC ; ;total size of all files ; LD A,(NUMCOL) ;if number of columns less than 3 CP 3 ;then print crlf and gobble 2 spaces JR NC,SIZOV3 CALL CRLF## LD HL,SIZMSG+2 JR SIZPRT SIZOV3: LD HL,SIZMSG SIZPRT: CALL PSTR## LD HL,(FSIZ) CALL PB2ASC ; ;space free on disk ; LD HL,FREMSG CALL PSTR## LD HL,(FREE) CALL PB2ASC ; ;time to transfer entire disk, calculate seconds mod 60 and add to ;minutes and minutes mod 60 and add to hours as required. ; LD HL,TIMMSG CALL PSTR## ; LD HL,(TSECS) LD A,60 ;divide seconds by 60 CALL DIVHA ;seconds divided by minutes PUSH HL LD L,H LD H,0 LD (TSECS),HL ;remainder is seconds POP HL LD D,0 LD E,L LD HL,(TMINS) ;now add quotient to minutes ADD HL,DE LD A,60 CALL DIVHA ;minutes divided by 60 PUSH HL LD L,H LD H,0 LD (TMINS),HL ;remainder is minutes POP HL LD H,0 ;quotient in l is hours ; ;don't need to format hours ; CALL PB2ASC LD A,':' CALL COUT## ; ;format minutes to 2 characters ; LD DE,(TMINS) CALL PTFMT2 LD A,':' CALL COUT## ; ;need to format seconds as well ; LD DE,(TSECS) CALL PTFMT2 LD HL,BPSMSG CALL PSTR## ; ;show baudrate used for calculation ; LD HL,BPSTAB LD D,0 LD A,(BAUDCD) ld e,a add a,e add a,e add a,e add a,e LD E,A ADD HL,DE CALL PSTR## ; ;wrap it up ; LD HL,CLSMSG CALL PSTR## CALL CRLF## JP EXIT ; ;messages ; USRMSG: DB '>> Files: ',0 SIZMSG: DB ' Used: ',0 FREMSG: DB 'k Free: ',0 TIMMSG: DB 'k Time: ',0 BPSMSG: DB ' at ',0 CLSMSG: DB ' baud',0 ; ;subroutines: ;~~~~~~~~~~~ ; ;multiply h*a hl=result ; MULHA: LD B,A ;set counter LD D,0 LD E,H LD L,H LD H,0 MULLP: DEC B RET Z ADD HL,DE JR MULLP ; ;divide hl/a h=remainder, l=quotient ; DIVHA: PUSH BC LD B,8 LD C,A DIV2: XOR A ADD HL,HL LD A,H SUB C JP M,DIV3 LD H,A LD A,L OR 1 LD L,A DIV3: DEC B JP NZ,DIV2 POP BC RET ; ;shift hl one right ; SHFTHL: LD A,L RRA LD L,A OR A ;clear carry LD A,H RRA LD H,A RET NC LD A,80H OR L LD L,A RET ; ;prints de as 2 or 3 characters left padded with spaces ; PTFMT2: PUSH DE ;save number LD HL,99 AND A ;clear carry SBC HL,DE ;de > 99 ? JR C,PRT00 ;3 digits LD A,E CP 10 JR NC,PRT00 ;2 digits LD A,'0' CALL COUT## JR PRT00 ;1 digit (leading 0) PTFMT: PUSH DE ;save number ld hl,999 and a sbc hl,de jr c,prt00 LD HL,99 AND A ;clear carry SBC HL,DE ;de > 99 ? JR C,PRT0 ;filesize > 99 LD A,E CP 10 ;2 digits? JR NC,PRT1 ;filesize < 100 > 9 PRT2: ;must be single digit LD A,' ' CALL COUT## PRT1: ;2 digits LD A,' ' CALL COUT## PRT0: ld a,' ' call cout## prt00: POP HL CALL PB2ASC ;print size RET ; ;prints binary number in hl as decimal number with no leading spaces ; PB2ASC: LD A,H OR L ;see if 0 JR Z,PZERO ;yes so skip all this next stuff PUSH IY ;save register XOR A LD (PBFLG),A ;show no digit printed yet LD IY,P10 ;point to powers of ten table PBLP0: XOR A ;clear digit count LD D,(IY+1) LD E,(IY) PBLP1: OR A ;clear carry SBC HL,DE ;sub pow of 10 JP C,PBJP1 ;finished INC A ;bump count JP PBLP1 PBJP1: ADD HL,DE ;make positive ADD A,30H CP '0' ;see if a 0 JP NZ,PBJP1B ;if not then print it ; PBFLG EQU $+1 LD A,0 ;if is 0 then get flag CP 1 ;see if before 1-9 digit JP Z,PBJP1A ;no, so print it JP PBJP2 ;yes, so don't print PBJP1A: LD A,'0' ;restore digit PBJP1B: PUSH HL PUSH DE CALL COUT## ;print digit POP DE POP HL LD A,1 LD (PBFLG),A ;set character printed flag PBJP2: INC IY INC IY ;point next power of ten LD A,E CP 1 ;see if 5 digits yet JP NZ,PBLP0 POP IY ;restore msgarr pointer RET ;done P10: DW 10000 DW 1000 DW 100 DW 10 DW 1 ; PZERO: LD A,'0' CALL COUT## RET ; NEWLIN: LD A,(NUMCOL) ;reset counter LD (COLCNT),A CALL CRLF## LD A,(LINCNT) DEC A LD (LINCNT),A ;save new line count OR A CALL Z,PGPAUS ;wait for keystroke RET PGPAUS: LD A,(NUMLIN) ;reset counter LD (LINCNT),A CALL PRINT## DB ' [ More ]',13,0 WAIT: CALL CONDIN## JR Z,WAIT CP 'C'-40H JP Z,EXIT ;ctrl-c ends it all RET ; HELP: CALL PRINT## DB CR,LF,LF DB 'Remote DIRectory v1.5+ -- (c)1984 Simon J. Ewins' DB CR,LF,LF DB 'Usage:',CR,LF,LF DB 'RDIR :show all files with xfer times at current baudrate' DB CR,LF DB 'RDIR /s :show all files + system files + xfer times' DB CR,LF DB 'RDIR /a :show all files in all user areas + xfer times' DB CR,LF DB 'RDIR /b# :change baudrate times to # (0-7)' DB CR,LF,LF DB 'Any combination of /asb# is allowed.' DB CR,LF,LF DB 'RDIR du:afn.aft /options (drive/user & wildcards allowed).' DB CR,LF,LF DB '/options may be disallowed on some systems.' DB CR,LF,LF,0 JP EXIT ; NOFILE: CALL PRINT## DB CR,LF,LF DB '>>> ',0 LD A,(CURDRV) ADD A,41H CALL COUT## LD A,(CURUSR) LD H,0 LD L,A CALL PB2ASC CALL PRINT## DB ': No files (',0 LD HL,(FREE) CALL PB2ASC CALL PRINT## DB 'k free) <<<' DB CR,LF,LF,0 JP EXIT ; ; ;* END ;*