; LUX - A Library extension system - Version 77B as of 10/11/87 ; ;----------------------------------------------------------------------- ; ; 10/11/87 Revised to work with Steven Greenberg's LDIR-B program. ; v77B Can now specify filetype correctly, defaults to .ARK, ARC ; then .LBR type if no filetype included. ; - Irv Hoff ; ; 03/27/87 Revised to work with TeleVideo products and Zorba computers. ; v77A They do not retain (IX) and (IY) values during BDOS calls. ; - Irv Hoff ; ; 03/01/87 Restored LUX v77 to the original intent of the LUX 7x ver- ; sion. I had already skipped to LUX70 to not place Tom Brady ; in a position where he could not continue working with his ; LUX54, calling any subsequent version LUX55. Instead he ; elected to try to totally obliterate any work I had put into ; this program. I will not allow that to occur. Many people ; prefer my version to his, since it can be installed on any ; RCPM as fast as you can extract the files from the libaray. ; - Irv Hoff ; ; 02/28/87 [Tom Brady totally replaced everything in the LUX70A version ; v75 including all auxiliary programs in the library with his own ; LUX54 version. He further decided to jump to LUX75. This ; was done in an obvious attempt to force people to use only ; his version. This note by Irv Hoff] ; - Tom Brady ; ; 02/27/87 Added an equate to select MBKMD120 which came out about the ; v70A same time that LUX70 was being released. LUX70A supports ; KMD, MBKMD and NUKMD. Be sure to make the proper selection. ; - Irv Hoff ; ; 02/22/87 MAJOR CHANGE... Rewrote program to use conventional files ; v70 normally found on A0: ; ; LCHEK.COM (Current is LCHEK11.COM) ; DIR.COM (Renamed SD.COM with $L option) ; TYPE.COM (Should handle both squeezed and crunched) ; UNARC.COM (Combination DIR and TYPE for .ARC/.ARK files) ; ; Special files such as LUXCHK, LUXDIR, LUXTYPE, etc. on ; a special drive/user area (usually A15:) no longer needed. ; This greatly simplifies the installation and use of LUX. ; Wheel byte, MAXDRV and MAXUSR bytes no longer used or even ; needed - LUX can be only be called up in whatever drive/user ; area you are currently in, which in itself is the limiting ; factor. This is a radical departure from previous versions ; so the version number has been significantly advanced. This ; allows additional updates of conventional versions if others ; want an additional choice. This makes one universal version ; possible for any size system from small floppies to immense ; hard drives of 100 Mb and more. ; ; Option added to support KMD, MB-KMD or NUKMD added as the ; latter two must have must have both 'A' and 'L' capability ; for various functions. (KMD needs only the 'A', however it ; accepts 'L' interchangeably since versions prior to .ARC or ; .ARK files used 'L' for .LBR files.) Can now exit LUX with ; CTL-C, CTL-K or CTL-X. This standardizes exit with other ; similar programs. - Irv Hoff ; ; 09/09/86 None of the previous LUX files protected its start address, ; v54 allowing long programs to overrun LUX itself. It would then ; lock up the system until reset by the Sysop. This happened ; most often when using the TYPE command to look at lengthy ; .DOC files but was not limited to such files. Reformatted ; and simplified. - Irv Hoff ; ; 08/25/86 Modified for .ARK file support in addition to .ARC and .LBR. ; v53 - Norman Beeler ; ; 06/02/86 Modified for .ARC file support, using UNARCxx for DIR and ; v52 TYPE commands....fully automatic determination of .ARC or ; .LBR file extents, (extent not necessary). Supports .ARC ; member transfer. - Norman Beeler ; ; 06/26/85 Modified for KMD support throughout. Other cosmetic changes. ; v51 KMD offers total automatic protocol detect. (It also offers ; YMODEM-type batch transfers but this is not used with LUX.) ; - Tom Brady ; ; 07/21/85 Added SENDK and SK options for use with 1k blocks which are ; v50 needed for MEX114 and MS-DOS program with YMODEM protocol. ; (1k blocks are fully automatic with IMP. The 'SK' need not ; be manually inserted for 1k protocol.) ; - Steve Sanders ; ; 11/26/83 Original release. Adapted from ATTACH program. ; v12B - Steven Holtzclaw ; ;----------------------------------------------------------------------- ; .Z80 ; Needed for M80, otherwise ignore ; YES EQU 0FFH NO EQU 0 ; KMD EQU YES MBKMD EQU NO NUKMD EQU NO ; ;----------------------------------------------------------------------- ; ; Equates ; CR EQU 0DH LF EQU 0AH ; ;----------------------------------------------------------------------- ; ; ; If RCPM is Yes, change the BYECMD equate at end of this file if your ; logoff program is not called BYE.COM. ; RCPM EQU YES ; Yes, if being used with a RCPM system HLPMSG EQU YES ; Yes, if helpful messages are wanted AUTODR EQU YES ; Yes, if initial auto-directory wanted HLPERS EQU 2 ; Give auto-help after this many errors ; ; ;----------------------------------------------------------------------- ; ; The following files are normally on A0: and are for general purpose as ; well as for use with LUX. ; ; NOTE: LDIR.COM is actually LDIR-B.COM renamed. ; When choosing a drive, use: 0=A, 1=B, etc. ; DIRDRV EQU 0 ; Drive number for LDIR.COM DIRUSR EQU 0 ; User number for LDIR.COM ; KMDRV EQU 0 ; Drive number for KMD, MB-KMD or NUKMD KMDUSR EQU 0 ; User number for KMD, MB-KMD or NUKMD ; TYPDRV EQU 0 ; Drive number for TYPE.COM TYPUSR EQU 0 ; User number for TYPE.COM ; UNADRV EQU 0 ; Drive number for UNARC.COM UNAUSR EQU 0 ; User number for UNARC.COM ; ;----------------------------------------------------------------------- ; BDOS EQU 0005H ; Jumper vector for BDOS calls TPA EQU 0100H ; CP/M program area FCB1 EQU 005CH ; First file control block FCB2 EQU 006CH ; Second file control block REBOOT EQU 0000H ; Cold reboot address TBUFF EQU 0080H ; Default command buffer ; ; ; Macros used ; DRVUSR MACRO DRIVNO,USERNO,FNCNAM,RTN1,RTN2,RTN3,RTN4 CALL FILTYP DEFB DRIVNO+'A' ; USERN1 DEFL USERNO ; IF USERN1 GT 9 DEFB (USERN1 /10)+'0' ; USERN1 DEFL USERN1-10 ENDIF ; USERN1 GT 9 ; DEFB USERN1+'0' DEFB ':' DEFB FNCNAM DEFB 0 ; IF NOT NUL RTN1 CALL RTN1 ENDIF ; NOT NUL RTN1 ; IF NOT NUL RTN2 CALL RTN2 ENDIF ; NOT NUL RTN2 ; IF NOT NUL RTN3 CALL RTN3 ENDIF ; NOT NUL RTN3 ; IF NOT NUL RTN4 CALL RTN4 ENDIF JP PROCES ; NOT NUL RTN4 ENDM ; DVUS MACRO DRIVNO,USERNO,FNCNAM,RTN1,RTN2,RTN3,RTN4 CALL FILTYP DEFB DRIVNO+'A' ; USERN2 DEFL USERNO ; IF USERN2 GT 9 DEFB (USERN2 /10)+'0' USERN2 DEFL USERN2-10 ENDIF ; USERN2 GT 9 ; DEFB USERN2+'0' DEFB ':' DEFB FNCNAM DEFB 0 ENDM ; CMDJMP MACRO VERB,VECTOR CALL ILCMP DEFB VERB DEFB 0 JP NC,VECTOR ENDM ; ;======================================================================= ; ; Program starts here ; ;======================================================================= ; START: LD SP,SSTACK ; Starting stack CALL ILPRT DEFB CR,LF,'LUX v77B' ; IF AUTODR DEFB 0 ENDIF ; AUTODR ; DEFB CR,LF,0 ; ; ; Check for a blank or null command line ; LD A,(TBUFF+1) ; Get byte from default command buffer OR A ; If non-zero then there is a possible JP NZ,GTDVUS ; File specified ; SPCERR: CALL ILPRT ; Print the error message DEFB CR,LF DEFB '++ Examples of valid LUX commands ++',CR,LF,LF DEFB ' LUX HELLO.ARC',CR,LF DEFB ' LUX HELLO.ARK',CR,LF DEFB ' LUX HELLO.LBR',CR,LF,LF DEFB ' The extent is not needed if no other ',CR,LF DEFB ' library files have a similar name.' DEFB CR,LF,0 JP REBOOT ; Reboot since we have overwritten CCP ;..... ; ; GTDVUS: LD HL,TBUFF+2 ; Index default key buffer CALL DRUSR ; Get requested drive/user JP C,SPCERR ; ; ; Test for drive/user within range ; LD (RQDDRV),BC ; Set the requested drive/user EX DE,HL ; DE is source address to create new FCB LD HL,FCB1 ; Index FCB CALL SCANR1 ; Create the new FCB ; ; ; Force the default file type ; LD A,(FCB1+9) ; See if any filetype included CP ' ' JP Z,EXT1 ; If not, exit LD A,1 LD (EXTFLG),A ; Otherwise set extent flag ; ; ; Get the library name from the FCB and store it ; EXT1: LD HL,FCB1 ; Source for move LD DE,LBRNAM-1 ; Destination for move LD BC,9 ; Max 8 character filename LDIR ; Move to local name LD HL,FCB1+1 ; First byte of filename LD A,'?' ; Character to look for LD BC,8 ; Search thru 11 bytes CPIR ; Do search JR NZ,LOOKUP ; No ? found - continue CALL ILPRT ; Print the error message DEFB CR,LF DEFB '++ Ambiguous filenames are not allowed ++',CR,LF,0 JP SPCERR ;..... ; ; ; Look for the filename on directory ; LOOKUP: CALL GETOLD ; Get the current drive/user CALL SETNEW ; Set requested drive/user LD DE,080H ; Default DMA address LD C,26 CALL SPBDOS ; Set the DMA address LD A,(EXTFLG) ; See if filetype was included OR A JR Z,LOOK1 ; If not, exit ; LD DE,FCB1 ; Index filename specified LD C,17 CALL SPBDOS ; Search for first INC A ; Does file exist? JP NZ,SETFIL ; Yes, so go JP NOFILE ; Else no match, show error ; LOOK1: LD HL,'RA' ; Try .ARK file LD (FCB1+9),HL LD A,'K' ; Set .ARK LD (FCB1+11),A LD DE,FCB1 ; Index filename specified LD C,17 CALL SPBDOS ; Search for first INC A ; Does file exist? JP NZ,SETARK ; Yes, so go ; LD HL,'RA' ; Try .ARC file LD (FCB1+9),HL LD A,'C' ; Set .ARC LD (FCB1+11),A LD DE,FCB1 LD C,17 ; See if it exists CALL SPBDOS INC A JP NZ,SETARC ; Yes, so go ; LD HL,'BL' ; Try .LBR file LD (FCB1+9),HL LD A,'R' ; Set .LBR LD (FCB1+11),A LD DE,FCB1 LD C,17 ; See if it exists CALL SPBDOS INC A JP NZ,PRESTR ; Yes, so go ; JP NOFILE ; No, error off ;..... ; ; ; Was an .ARC file so set flags ; SETARC: LD A,0FFH ; Yes, set ARCFLG LD (ARCFLG),A JP PRESTR ;..... ; ; ; Was an .ARK file so set flags ; SETARK: LD A,7FH ; Yes, set ARCFLG and .ARK LD (ARCFLG),A ; PRESTR: LD HL,FCB1 LD DE,LBRNAM-1 ; Update library name (.ARC) LD BC,12 LDIR JP PGMSTR ; Go do it ;..... ; ; ; Was the same as requested, find which ; SETFIL: LD A,(FCB1+11) AND 7FH ; Strip off any archive bits, etc. CP 'C' JP Z,SETARC CP 'K' JP Z,SETARK CP 'R' JP Z,PRESTR ; CALL ILPRT DEFB CR,LF,'Not an archive or library file',CR,LF,0 JP REBOOT ; Reboot since we have overwritten CCP ;..... ; ; NOFILE: CALL SETOLD CALL ILPRT ; Print the error message ; IF AUTODR DEFB CR,LF ENDIF ; AUTODR ; DEFB CR,LF,'Can''t find ',0 CALL DVUPRT CALL NAMPRT ; Print the filename CALL ILPRT DEFB ' - check the DIR',CR,LF,0 JP REBOOT ; Reboot since we have destroyed the ccp ;..... ; ; DEFS 64 ; 32 level stack for here ; SSTACK EQU $ ; FINIS EQU $ ; Finish of program loader ; LODLEN EQU FINIS-START ; Length of loader ; Keep the program in line DEFS 300H-LODLEN ; Add extra bytes here to make ; 'PGMSTR' start on a 100h byte boundary ; ;----------------------------------------------------------------------- ; ; This is the start of the relocated program - all of the code from ; 'START' to here is thrown away once LUX begins execution. ; ;----------------------------------------------------------------------- ; ; set up the BDOS and BIOS patches ; PGMSTR: JP INIT ; Jump to start of this module DEFB 'LUX v77B' ; The name 'LUX' is a clue to other ; programs that enables them to deter- ; mine if LUX is resident. 'L' is at ; BDOS+3 when LUX is resident. ; ; This is the LUX removal routine, jumped to by the BYE command. It is ; accessable to external programs and is defined to exist at LUX+12 ; (looks like BDOS+12 when LUX is resident). ; REMOVE: IF RCPM LD SP,TPA+100H ; Use the TPA for a stack LD BC,0 ; First select A0: CALL RESET LD DE,80H ; Clear the DMA buffer PUSH DE PUSH DE LD B,128 ; Bytes to clear XOR A ; Easy way to make A=0 ; RZRLP: LD (DE),A ; Null the location INC DE ; Next address DJNZ RZRLP ; Loop until 'B' is zero ; LD A,BYELEN ; Store away the length of the command LD HL,BYECMD ; Now move the commands to the DMA LD (HL),A POP DE ; Restore the DMA address LD BC,BYELEN LDIR ; POP DE ; Restore it again LD C,26 ; Reset the DMA CALL SPBDOS LD DE,SUBFCB ; Address the .SUB file FCB LD C,22 ; Make the file CALL SPBDOS INC A ; Check for errors JR Z,EXITER ; Oops, no directory space LD DE,SUBFCB ; Else write the data LD C,21 CALL SPBDOS INC A JR Z,EXITER ; Oops, no space left LD DE,SUBFCB LD C,16 ; Now close the file CALL SPBDOS LD HL,0 ; Now make the exit routine go to A0: LD (OLDDRV),HL ENDIF ; RCPM ; JP UNPATH ; Unpatch the jump table, and warm boot ;..... ; ; ; Error handler for REMOVE routine ; IF RCPM EXITER: CALL ILPRT ; An error when making the .SUB file DB CR,LF,'+ Error: Can''t remove LUX! Please +' DB CR,LF,'+ type CTRL-C to exit LUX, +' DB CR,LF,'+ then type BYE to logoff. +',0 LD SP,STACK JP GETCMD ENDIF ; RCPM ;..... ; ; ; This is the LUX intialization ; INIT: LD HL,(0005H+1) ; Get BDOS start LD (PGMSTR+1),HL ; Set new jump to BDOS LD HL,PGMSTR ; Get local bdos vector LD (0005H+1),HL ; Set it in low memory LD SP,STACK ; Reset stack LD HL,(0000H+1) ; Get BIOS warm boot vector LD (BIOS3),HL ; Save old warm boot vector ; ; ; Save the old BIOS vectors ; LD HL,(BIOS3) ; BIOS warm boot address LD DE,OWBOOT ; Local warm boot address LD BC,12 ; 12 bytes to move LDIR ; Move the block ; ; ; Set up the new BIOS vectors ; LD HL,WBOOT ; Source is local table LD DE,(BIOS3) ; Destination is old BIOS LD BC,12 ; 12 bytes to move LDIR ; Move the block LD A,0FFH ; Set the auto-directory byte LD (DOADIR),A XOR A ; Reset the error count LD (HLPCNT),A ; JP ENTRY ; Initialize ;..... ; ; OWBOOT: DEFB 0,0,0 ; Old WBOOT vector is moved to here OCONST: DEFB 0,0,0 ; Old CONSTAT vector is moved to here OCONIN: DEFB 0,0,0 ; Old cONIN vector is moved to here OCONOU: DEFB 0,0,0 ; Old CONOUT vector is moved to here ; WBOOT: JP ENTRY ; Vector warm boot to entry CONST: JP VCONST ; Check for carrier CONIN: JP VCONIN ; Vector conin to CONIN CONOU: JP VCONOU ; Vector to CONOUT ; VCONST: JP OCONST ; Jump to old CONSTAT routine ; VCONOU: JP OCONOU ; Jump to old CONOUT routine ; VCONIN: CALL OCONIN ; Get a byte CP 'C'-40H ; CTL-C? JR Z,VCON1 CP 'K'-40H ; CTL-K? JR Z,VCON1 CP 'X'-40H ; CTL-X? RET NZ ; Nope - let BIOS have it ; VCON1: LD A,(ACTIVE) ; Is LUX segment active? OR A LD A,3 RET Z ; Not active - let BIOS have it ; LD SP,TPA ; Re initialize the stack CALL ILPRT ; Print the following DEFB ' Exiting LUX',CR,LF,0 ; UNPATH: LD HL,OWBOOT ; Index old warm boot vector LD DE,(BIOS3) ; BIOS jump table LD BC,12 ; 12 bytes to move LDIR ; Move the old table back CALL SETOLD ; Set old drive/user JP REBOOT ; Warm boot - end of program ;..... ; ; ; This is the LUX entry point ; ENTRY: LD SP,STACK ; Set up local stack LD HL,PGMSTR ; Dummy BDOS vector LD (6),HL ; Set it LD HL,(BIOS3) ; BIOS warm boot vector LD (1),HL ; Set it LD A,0C3H ; (JMP) LD (0),A ; Reset warm boot jump LD (5),A ; And BDOS jump CALL OCONST ; See if character waiting OR A ; Test result JR Z,ENTR1 ; If no character is waiting CALL OCONIN ; Get the console character ; This is done to gobble any ; Possible garbage character ; ENTR1: LD A,0FFH LD (ACTIVE),A ; Set LUX active ; GETCMD: CALL SETNEW ; Reset drive/user LD IX,TBUFF+1 ; Place to put command string LD IY,TBUFF+0 ; Length of command XOR A LD (IY+0),A ; IF AUTODR LD A,(DOADIR) ; Shall we do a directory? OR A JR Z,PROMPT ; Guess not XOR A ; Else zap the byte LD (DOADIR),A LD A,3 ; Fake a DIR command LD (CMDLEN),A LD HL,'ID' LD (CMDLIN+2),HL LD L,'R' LD H,0 LD (CMDLIN+4),HL JP GOCNV ; And do it ENDIF ; AUTODR ;..... ; ; PROMPT: IF HLPMSG CALL ILPRT ; Print the entry message DEFB CR,LF,'LUX v77B - ^C, ^K or ^X to exit, ? for menu' DEFB CR,LF,0 ENDIF ; HLPMSG ; PRMPT2: CALL CRLF CALL DVUPRT ; Print the LUX prompt CALL NAMPRT ; Drive/user, library name CALL ILPRT DEFB ' -->',0 LD DE,CMDLIN ; Index command line LD C,10 CALL SPBDOS ; Read console buffer LD A,(CMDLEN) ; Get command length OR A ; Test it JR Z,GETCMD ; If null command LD A,(CMDLIN+2) ; Get first character CP ';' ; Semicolon ok JP Z,PRMPT2 ; GOCNV: CALL CNVBUF ; Convert the command line to upper case LD DE,CMDLIN+2 ; Index data from the command line LD A,(ARCFLG) ; Are we looking at .ARC files? OR A JR Z,LBRCMD ; Nope, do .LBR commands BIT 7,A JR Z,ARKFL CMDJMP 'FILES',ACFILES JR REST ; ARKFL: CMDJMP 'FILES',AKFILES ; REST: CMDJMP 'TYPE',ATYPE CMDJMP 'DIR',UNARC CMDJMP 'D',UNARC CMDJMP 'SD',UNARC CMDJMP 'CHEK',NOARC1 JR HLP ; LBRCMD: CMDJMP 'TYPE',TIPE ; File type command process CMDJMP 'DIR',DIR ; Directory command process CMDJMP 'D',DIR ; Alternate for DIR CMDJMP 'SD',DIR ; Alternate for DIR CMDJMP 'FILES',FILES ; Run LDIR.COM ; HLP: CMDJMP '?',QKHELP ; Alternate for HELP CMDJMP 'LUX',LUX ; LUX command process ; ; ; If there are other commands a user may use on your system, and you ; want to tell him to exit LUX first, then enter below: ; ; CMDJMP 'CMD',NOGOT. ; ; Place your command in 'CMD' and it will tell the user that that com- ; mand is only available outside of LUX. ; IF RCPM AND KMD CMDJMP 'KMD',KKMD ; KMD command process ENDIF ; RCPM AND KMD ; IF RCPM AND MBKMD CMDJMP 'MBKMD',KKMD ; NUKMD command process ENDIF ; RCPM and MBKMD ; IF RCPM AND NUKMD CMDJMP 'NUKMD',KKMD ; NUKMD command process ENDIF ; RCPM and NUKMD ; IF RCPM CMDJMP 'SEND',SEND ; Synonym for KMD S, MBKMD S or NUKMD S CMDJMP 'SENDK',SENDK ; Synonym for KMD SK, MBkMD SK or NUKMD SK CMDJMP 'CHAT',NOGOT ; Tell user NOGOT here CMDJMP 'BYE',NOGOT ; Tell user NOGOT here ENDIF ; RCPM ; ; ; This will actually print the command in error like this ; ; ERROR, DUR is not a valid LUX command. ; CALL ILPRT DEFB CR,LF,LF,'ERROR, ',0 ; Point at command error CALL PRTERR ; Print the command just entered LD A,' ' ; And a space CALL CTYPE LD HL,HLPCNT ; Address the error count INC (HL) ; Bump it LD A,HLPERS ; Have we reached the limit? CP (HL) ; JR NZ,KPTRYN ; No, jump around the rest LD (HL),0 ; Else reset the count JP QKHELP ; And give him help anyway ;..... ; ; KPTRYN: CALL ILPRT ; Tell them it's no good DEFB ' is not a valid LUX command.',CR,LF,0 JP GETCMD ;..... ; ; PRTERR: LD HL,CMDLIN+2 ; Index command just entered LD A,(CMDLEN) ; Get the length LD B,A ; Into 'B' ; GETCM5: LD A,(HL) ; Get a byte CP 020H ; Space ? JR Z,GETCM6 ; Yes - dont print it CP 00H ; Null JR Z,GETCM6 ; Yes - all done CALL CTYPE ; Print the character INC HL ; Next character DJNZ GETCM5 ; Loop for the rest ; GETCM6: RET ; ; ; 'COMMAND TRANSLATION VECTORS ; ; 'SUMMARY OF AUX ROUTINES: ; ; 'FILTYP' installs the following 'DEFB' into new command line ; specify the drive and user area for each command as in ; the vectors below. remember each 'DEFB' must end with a ; zero. ; ; 'FILNAM' installs the current .LBR name into the new command line ; ; 'FILSPC' installs a space character into the new command line ; ; 'FILMEM' installs the requested member name into the new command line ; ; ACFILES:DRVUSR DIRDRV,DIRUSR,'DIR *.ARC' AKFILES:DRVUSR DIRDRV,DIRUSR,'DIR *.ARK' FILES: DRVUSR DIRDRV,DIRUSR,'DIR *.LBR' ; ATYPE: DRVUSR UNADRV,UNAUSR,'UNARC ',FILNAM,FILSPC,FILMEM DIR: DRVUSR DIRDRV,DIRUSR,'LDIR ',FILNAM,FILSPC,FILMEM TIPE: DRVUSR TYPDRV,TYPUSR,'TYPE ',FILNAM,FILSPC,FILMEM UNARC: DRVUSR UNADRV,UNAUSR,'UNARC ',FILNAM ; IF RCPM AND KMD SEND: DRVUSR KMDRV,KMDUSR,'KMD A ',FILNAM,FILSPC,FILMEM SENDK: DRVUSR KMDRV,KMDUSR,'KMD AK ',FILNAM,FILSPC,FILMEM SENDA: DRVUSR KMDRV,KMDUSR,'KMD A ',FILNAM,FILSPC,FILMEM SENDAK: DRVUSR KMDRV,KMDUSR,'KMD AK ',FILNAM,FILSPC,FILMEM ENDIF ; RCPM AND KMD ; IF RCPM AND NUKMD OR MBKMD SEND: LD A,(ARCFLG) ; Are we in an .ARC file? OR A JP NZ,SENDA ; Yes, use 'A' for .ARC JP SEND1 ; No, use 'L' for .LBR ; SENDK: LD A,(ARCFLG) ; Are we in an .ARC file? OR A JP NZ,SENDA ; Yes, use 'A' for .ARC JP SENDK1 ; No, use 'L' for .LBR ENDIF ; RCPM AND MBKMD OR NUKMD ; IF RCPM AND MBKMD SEND1: DRVUSR KMDRV,KMDUSR,'MBKMD L ',FILNAM,FILSPC,FILMEM SENDK1: DRVUSR KMDRV,KMDUSR,'MBKMD LK ',FILNAM,FILSPC,FILMEM SENDA: DRVUSR KMDRV,KMDUSR,'MBKMD A ',FILNAM,FILSPC,FILMEM SENDAK: DRVUSR KMDRV,KMDUSR,'MBKMD AK ',FILNAM,FILSPC,FILMEM ENDIF ; RCPM AND MBKMD ; IF RCPM AND NUKMD SEND1: DRVUSR KMDRV,KMDUSR,'NUKMD L ',FILNAM,FILSPC,FILMEM SENDK1: DRVUSR KMDRV,KMDUSR,'NUKMD LK ',FILNAM,FILSPC,FILMEM SENDA: DRVUSR KMDRV,KMDUSR,'NUKMD A ',FILNAM,FILSPC,FILMEM SENDAK: DRVUSR KMDRV,KMDUSR,'NUKMD AK ',FILNAM,FILSPC,FILMEM ENDIF ; RCPM AND NUKMD ; ; ; Quick help summary ; QKHELP: CALL ILPRT DEFB CR,LF,LF DEFB 'You are using the LUX utility to work with an archive ' DEFB CR,LF DEFB 'or library file. These are the available commands:' DEFB CR,LF,LF DEFB 'DIR - Display member files ' DEFB 'in this library',CR,LF DEFB 'FILES - Display other .ARC/.ARK/.LBR ' DEFB 'files available',CR,LF DEFB 'LUX NEWNAME - Attach to another ' DEFB 'LBR/ARC file ',CR,LF ; IF RCPM AND KMD DEFB CR,LF DEFB 'KMD S HELLO.EXT - Sends member file ' DEFB 'via auto-protocol detect',CR,LF DEFB 'KMD SK HELLO.EXT - Sends member file ' DEFB 'with manual 1k setting',CR,LF ENDIF ; RCPM AND KMD ; IF RCPM AND MBKMD DEFB 'MBKMD S HELLO.EXT - Sends member file ' DEFB 'via auto-protocol detect',CR,LF DEFB 'MBKMD SK HELLO.EXT - Sends member file ' DEFB 'with manual 1k setting',CR,LF ENDIF ; RCPM AND MBKMD ; IF RCPM AND NUKMD DEFB 'NUKMD S HELLO.EXT - Sends member file ' DEFB 'via auto-protocol detect',CR,LF DEFB 'NUKMD SK HELLO.EXT - Sends member file ' DEFB 'with manual 1k setting',CR,LF ENDIF ; RCPM AND NUKMD ; IF RCPM DEFB 'SEND HELLO.EXT - Same as ''S'' command',CR,LF DEFB 'SENDK HELLO.EXT - Same as ''SK'' command',CR,LF ENDIF ; RCPM ; DEFB CR,LF DEFB 'TYPE HELLO.EXT - Display ASCII file contents' DEFB CR,LF,CR,LF DEFB '? - Displays this menu' DEFB CR,LF,LF,'(Abort to CP/M with ^C, ^K or ^X)',CR,LF DEFB 0 JP GETCMD ;..... ; ; ; Tried entering CHAT - tell him to exit LUX first. Add other commands ; as you wish. ; NOGOT: CALL CRLF CALL CRLF CALL PRTERR ; Print the command CALL ILPRT ; And then this DEFB ' <<== Exit LUX with ^C, ^K or ^X',CR,LF,0 JP GETCMD ; Go back for another command ;..... ; ; NOARC1: CALL CRLF CALL CRLF CALL ILPRT DEFB 'Use DIR command for CRC values',CR,LF,0 JP GETCMD ;..... ; ; ; KMD is a special case since the 'A' and 'R' options are invalid here ; IF RCPM KKMD: CALL ADVANC ; Go to next character LD A,(HL) ; Get the character CP 'S' ; If 'S' check for JR Z,KKMD1 ; Following 'K' CP 'R' ; Not legal here JR Z,KKMD2 ; Execute error routine CP 'A' ; Not legal here JR Z,KKMD3 ; Execute error routine CP 'L' ; Not legal here JR Z,KKMD3 ; Execute error routine ENDIF ; RCPM ; IF RCPM AND KMD DRVUSR KMDRV,KMDUSR,'KMD' ENDIF ; RCPM AND KMD ; IF RCPM AND MBKMD DRVUSR KMDRV,KMDUSR,'MBKMD' ENDIF ; RCPM AND MBKMD ; IF RCPM AND NUKMD DRVUSR KMDRV,KMDUSR,'NUKMD' ENDIF ; RCPM AND NUKMD ; IF RCPM KKMD1: INC HL ; Get next chacter LD A,(HL) CP 020H ; Is it a space? JR Z,KKMD1A CP 'K' ; Or packet request? JR Z,KKMDK ; KKMD1A: CALL NXTSPC LD A,(ARCFLG) ; Are we in an .ARC file? OR A JP Z,SEND ; Nope, send regular JP SENDA ; Yes, send .ARC ;..... ; ; KKMDK: CALL NXTSPC LD A,(ARCFLG) ; Are we in an .ARC file? OR A JP Z,SENDK ; Nope, send regular JP SENDAK ; Yes, send .ARC ;..... ; ; KKMD2: CALL CRLF CALL PRTERR ; Print the command CALL ILPRT ; Print the following DEFB ' can''t (R)eceive while in LUX',CR,LF,0 JP GETCMD ; Return to command ;..... ; ; KKMD3: CALL CRLF CALL PRTERR ; Print the command CALL ILPRT ; Print the following DEFB ' uses S or SK options while in LUX',CR,LF,0 JP GETCMD ENDIF ; RCPM ;..... ; ; ; 'LUX' command process ; LUX: LD A,(CMDLEN) ; Get the length of the command line CP 3 ; Was input only 'LUX' JP Z,LUX04 ; Error... CALL FNDSPC ; Find a space in command line JP C,LUX05 ; Error if no space found CALL ADVANC ; Search for the next non-blank character JP C,LUX05 ; Error if no more characters left CALL DRUSR ; Get drive/user JP C,LUX05 ; If drive/user specification error LD (TMPDRV),BC ; Save the temporary drive/user EX DE,HL ; De is source address to create new fcb LD HL,TMPFCB ; Index temporary fcb CALL SCANR1 ; Create the new fcb LD HL,'BL' ; Set 'LB' into first two bytes of file type LD (TMPFCB+9),HL LD A,'R' ; Set 'R' into last byte of file type LD (TMPFCB+11),A CALL SETTMP ; Log into the requested drive/user LD DE,080H LD C,26 ; BDOS set DMA function CALL 5 ; Set DMA address to 80h LD DE,TMPFCB ; Index temporary FCB LD C,17 ; Bdos search first function CALL 5 INC A ; Test for existence JR NZ,LUX01 ; OK, go LD HL,'RA' ; Check for .ARC file LD (TMPFCB+9),HL LD A,'C' LD (TMPFCB+11),A LD DE,080H LD C,26 CALL 5 LD DE,TMPFCB LD C,17 CALL 5 INC A JR NZ,SETFLG ; Set ARCFLG LD HL,'RA' ; Check for .ARK file LD (TMPFCB+9),HL LD A,'K' LD (TMPFCB+11),A LD DE,080H LD C,26 CALL 5 LD DE,TMPFCB LD C,17 CALL 5 INC A JR Z,LUX05 ; Cant find file LD A,07FH LD (ARCFLG),A ; Set .ARK flag true JR LUX02 ; SETFLG: LD A,0FFH ; Set .ARC flag true LD (ARCFLG),A JP LUX02 ;..... ; ; LUX01: LD A,0 ; Set .ARC flag false LD (ARCFLG),A ; LUX02: LD HL,(TMPDRV) ; Get temporary drive/user LD (RQDDRV),HL ; Set new drive/user LD HL,TMPFCB+1 ; Source address of new name LD DE,LBRNAM ; Current .lbr name LD BC,12 ; 8 character file name LDIR ; Move it CALL ILPRT ; For display neatness DEFB CR,LF,0 LD A,0FFH ; Set the auto-directory flag LD (DOADIR),A JP GETCMD ;..... ; ; LUX04: CALL ILPRT DEFB CR,LF,'++ Invalid drive/user number ++',CR,LF,0 JP GETCMD ;..... ; ; LUX05: CALL ILPRT DEFB CR,LF,LF,'Can''t find ',0 CALL DVUPR1 LD B,8 LD HL,TMPFCB+1 CALL NAMPR1 ; Print the file name CALL ILPRT DEFB ' - check your spelling',CR,LF,0 JP GETCMD ;..... ; ; PROCES: XOR A ; Zero last byte of new command line LD (IX+0),A LD HL,TBUFF+1 LD (HLPCNT),A ; Reset the error count CALL DRUSR ; Get drive/user LD (COMDRV),BC ; Set the .COM drive/user EX DE,HL ; De is source address to create new FCB CALL SCANER ; Create the new FCB EX DE,HL ; Into 'HL' LD DE,TBUFF+1 ; Start of command buffer PUSH HL PUSH DE OR A ; Clear any carry SBC HL,DE ; Calculate length of move LD A,(TBUFF) ; Get command line length SUB L ; Calculate new length LD (TBUFF),A ; Put new length LD A,07EH ; Calculate length of block move SUB L LD C,A ; Set into C LD B,0 ; 'B' gets zero POP DE ; Restore destination POP HL ; And source LDIR ; Move the block down LD HL,FCB1 ; Set up first FCB LD DE,TBUFF+1 CALL SCANR1 LD HL,FCB2 ; Set up second FCB CALL SCANR1 ; ; ; Force the default file type (.COM) ; LD HL,'OC' ; 'CO' LD (DEFFCB+9),HL LD A,'M' ; 'M' LD (DEFFCB+11),A XOR A ; Zero the record count and LD (DEFFCB+15),A ; the extent number LD (DEFFCB+32),A CALL SETCOM ; Set .COM drive/user LD DE,TPA LD C,01AH CALL SPBDOS ; Set DMA to TPA LD DE,DEFFCB LD C,011H CALL SPBDOS ; Search for first INC A JR NZ,PROCE1 ; File found CALL ILPRT DEFB CR,LF,'Can''t find ',0 LD B,8 LD HL,DEFFCB+1 CALL NAMPR1 ; Print the file name CALL ILPRT ; CR/LF DEFB CR,LF,0 JP ENTRY ; Go for more commands ;..... ; ; PROCE1: LD DE,TPA LD C,01AH CALL SPBDOS ; Set DMA to TPA LD DE,DEFFCB LD C,00FH CALL SPBDOS ; Open file INC A JR NZ,PROCE2 CALL ILPRT DEFB CR,LF,'.COM File error - notify SYSOP',CR,LF,0 JP ENTRY ;..... ; ; ; Load the .COM file into memory at 100h and call it ; PROCE2: LD HL,080H LD DE,080H ; LODCOM: ADD HL,DE ; Add record size offset EX DE,HL ; Get DMA address into 'DE' PUSH DE ; Save 'DE' and 'HL' PUSH HL LD C,01AH CALL SPBDOS ; Set DMA LD DE,DEFFCB ; Index .com file name LD C,014H CALL SPBDOS ; Read a record POP HL ; Restore 'DE' and 'HL' POP DE EX DE,HL ; 'HL' is dma address again OR A ; End of file ? JR Z,LODCOM ; No - read another record LD C,13 CALL SPBDOS ; Reset drive system CALL SETNEW ; Set new drive/user XOR A LD (ACTIVE),A ; Clear command mode active CALL CRLF CALL TPA ; Call the loaded file @100h LD DE,35 ; Zero out FCB1 LD HL,FCB1 ; ZEROFCB:LD (HL),0 INC HL DJNZ ZEROFCB JP ENTRY ; Go for more commands ;..... ; ; NAMPRT: LD B,8 ; 8 character file name LD HL,LBRNAM ; Index .LBR name ; NAMPR1: LD A,(HL) ; Get a byte CP 020H ; Space? JR Z,NAMPR2 ; Yes - dont print CALL CTYPE ; Else print the character ; NAMPR2: INC HL ; Next character DJNZ NAMPR1 ; Process 8 characters LD A,'.' ; Print a seperator CALL CTYPE LD B,3 ; 3 character file type ; NAMPR3: LD A,(HL) ; Get a character CALL CTYPE ; Print it INC HL ; Next character DJNZ NAMPR3 ; Process 3 characters RET ;..... ; ; ; Write a string of characters to the crt ; ILPRT: EX (SP),HL ; Save return address/get character pointer ; ILPRT1: LD A,(HL) ; Get a byte OR A ; Test it JR Z,ILPRT2 ; Null - end of string CALL CTYPE ; Else type the character INC HL ; Next character JR ILPRT1 ; Loop for more ; ILPRT2: INC HL EX (SP),HL ; Restore return address RET ; Return to caller ;..... ; ; ; Write a string of characters to the command line ; ; (works like ILPRT above) ; FILTYP: EX (SP),HL ; FILTY1: LD A,(HL) OR A JR Z,FILTY2 CALL PUTIN INC HL JR FILTY1 ; FILTY2: EX (SP),HL RET ;..... ; ; ; Puts ' $L' on command line ; FILDIR: CALL FILSPC LD A,'$' CALL PUTIN LD A,'L' CALL PUTIN ; ; ; Fill command line with a space ; FILSPC: LD A,20H ; Space character JP PUTIN ; Fill in ;..... ; ; ; Fill command line with .LBR name ; FILNAM: LD B,8 ; 8 character file name LD HL,LBRNAM ; Index .LBR name ; FILNA1: LD A,(HL) ; Get a character CP 020H ; Space ? JR Z,FILNA2 ; Yes - dont add to command line CALL PUTIN ; Put character into command line ; FILNA2: INC HL ; Next character DJNZ FILNA1 ; Process 8 characters LD A,'.' ; Put in a seperator character CALL PUTIN LD B,3 ; 3 character file type ; FILNA3: LD A,(HL) ; Get a character CALL PUTIN ; Put in command line INC HL ; Next character DJNZ FILNA3 ; Process 3 characters RET ; Return to caller ;..... ; ; ; Fill command line with member name ; FILMEM: CALL PARSER ; Parse member name LD HL,MEMBER ; Index member name LD B,12 ; 12 character max ; FILME1: LD A,(HL) ; Get a byte OR A ; End of input RET Z ; Yes - return CALL PUTIN ; Fill in one character INC HL ; Next character DJNZ FILME1 ; Continue looping RET ; Done ; PUTIN: LD (IX+0),A ; Stuff the character into command line INC IX ; Get ready for next character INC (IY+0) ; Bump command line length RET ; Return to caller ;..... ; ; ; Parse out a member name ; PARSER: LD HL,MEMBER ; Index member name LD B,12 ; Max 12 character filename ; PARSE1: LD (HL),0 ; Zero character INC HL ; Next character DJNZ PARSE1 ; Clear the entire member name CALL ADVANC ; Advance to the next non blank character RET C ; If at the end of the line LD DE,MEMBER ; DE is index to member, HL set by ADVANC LD HL,(NXTWRD) ; PARSE2: LD A,(HL) ; Get source byte OR A ; End of input line ? RET Z ; Yes - return ; LD (DE),A ; Put byte INC HL ; Next source INC DE ; Next destination JR PARSE2 ; Continue looping ;..... ; ; ; Advance the word at NXTWRD to the next non-blank address of the com- ; mand line. Set carry if no more characters available. ; ADVANC: LD HL,(NXTWRD) ; Get pointer to next word ; ADVAN1: LD A,(HL) ; Get a byte OR A ; Test flags JR Z,ADVAN3 ; Error - null character CP 020H ; Space ? JR NZ,ADVAN2 ; Yes - done INC HL LD (NXTWRD),HL ; Put pointer back JR ADVAN1 ; Loop for more ; ADVAN2: OR A ; Clear any carry RET ; ADVAN3: SCF ; Set error condition RET ;..... ; ; FNDSPC: LD HL,CMDLIN+2 ; Index command line ; FND01: LD A,(HL) ; Get a byte from command line OR A ; Eol ? JP Z,FNDER ; Error... CP 020H ; Space? JP Z,FNDEX ; Yes - go find requested file name INC HL ; Next character JR FND01 ; Else continue the search ; FNDER: SCF ; All chars. scanned and no space found RET ; FNDEX: LD (NXTWRD),HL ; Set character location OR A ; Assure carry reset RET ; ; NXTSPC: LD HL,(NXTWRD) ; Get pointer to next word ; NXTSP1: LD A,(HL) ; Get a byte OR A ; Is it a null? JR Z,NXTSP2 ; Yes - return CP 020H ; If at a space? JR Z,NXTSP2 ; Yes - return INC HL ; Next character JR NXTSP1 ; And continue looking ; NXTSP2: LD (NXTWRD),HL RET ;..... ; ; ; In-line compare. Compares string addressed by 'DE' to string after ; call (ends with zero). Return with carry set means strings not the ; same. All registers except 'A'-reg are unaffected. ; ILCMP: EX (SP),HL PUSH DE ; ILCMP1: LD A,(HL) ; Get a byte from source OR A ; Null JR Z,SAME1 ; Yes - same so far - test next char LD A,(DE) ; Get a byte from command string CP (HL) ; Same as source JR NZ,NOTSAM ; No - not the same INC HL ; Next source INC DE ; Next compare JR ILCMP1 ; Loop again ; NOTSAM: XOR A ; Zero for the test ; NSLP: INC HL ; Next immediate byte CP (HL) ; Null yet ? JR NZ,NSLP ; No - continue ; SAME2: SCF ; Set error condition ; SAME: EX DE,HL ; Get command string pointer LD (NXTWRD),HL ; Store it EX DE,HL ; Restore return address POP DE ; Restore source address INC HL ; Adjust to stack EX (SP),HL ; Replace return address RET ; Return ; SAME1: LD A,(DE) ; Get the next byte from command line OR A ; Null ? JR Z,SAME ; Yes - its ok CP 20H ; Space ? JR Z,SAME ; Yes - thats ok too... JR SAME2 ; Not ok- must be another character ;..... ; ; CTYPE: PUSH AF ; Save all registers PUSH BC PUSH DE PUSH HL AND 7FH ; Be sure its ASCII LD E,A ; Into 'E' LD C,2 ; Cpm console function CALL SPBDOS POP HL ; Restore all registers POP DE POP BC POP AF RET ; Return to caller ;..... ; ; CRLF: LD A,13 CALL CTYPE LD A,10 JR CTYPE ;..... ; ; ; Get the drive and user number for a file from command string index by ; 'HL' ; ; On entry: ; ; 'HL' points to first byte of the command string ; ; on exit: ; ; 'HL' points to the byte following ':' in the command string if ; the ':' was found in the first 4 character positions. ; -or- ; 'HL' points to the first byte of the command string if no ':' ; was found. ; ; 'C' contains the requested drive number (0-15) ; ; 'B' contains the requested user number (0-15) ; ; 'AF' the number of characters thru the ':' in the command string. ; ; 'CY' is set if drive or user number is out of range (0-15) ; ;----------------------------------------------------------------------- ; DRUSR: LD (TEMPHL),HL ; Save the pointer address LD IX,(TEMPHL) ; 'IX' get the pointer address LD BC,5 ; LD A,':' CPIR ; Search for the ':' LD A,C ; Get 'B' result from 'CPIR' instruction LD (LENGTH),A ; Keep for possible adjust EX DE,HL ; De points to the byte following ':' LD HL,VTABLE ; Index address table ADD HL,BC ; Add word offset ADD HL,BC LD A,(HL) ; Get routine lsb INC HL LD H,(HL) ; Get routine msb LD L,A LD BC,0 ; Set up drive/user storage JP (HL) ; Execute ;..... ; ; VTABLE: DEFW DRUS0 ; B=0 - FILENAME.EXT DEFW DRUS1 ; B=1 - A15:FILENAME.EXT DEFW DRUS2 ; B=2 - A1:FILENAME.EXT DEFW DRUS3 ; B=3 - A:FILENAME.EXT DEFW DRUS4 ; B=4 - :FILENAME.EXT ; ; ; Format was - FILENAME.EXT ; DRUS0: CALL GETDFU ; Get the default user CALL GETDFD ; Get the default drive LD HL,(TEMPHL) ; Get old buffer pointer back XOR A ; Zero move length RET ; All done ;..... ; ; ; Format was - DUU:FILENAME.EXT ; DRUS1: CALL GETDRV ; Get the drive parameter LD A,(IX+0) CP '0' JR C,ERROR CP '9'+1 JR NC,ERROR SUB '0' LD B,A ; Put in drive number SLA B ; * 2 SLA B ; * 4 SLA B ; * 8 ADD A,A ; A * 2 ADD A,B ; + c LD B,A INC IX ; Skip the tens digit JR GETUSR ; Get the user number ;..... ; ; ; Format was - DU:FILENAME.EXT ; DRUS2: CALL GETDRV ; Get the drive parameter JR GETUSR ; Get the user number ;..... ; ; ; Format was - D:FILENAME.EXT ; DRUS3: CALL GETDRV ; Get the drive parameter CALL GETDFU ; Get the default user ; ; ; Format was - :FILENAME.EXT ; DRUS4: JR DRUS5 ; GETDRV: LD A,(IX+0) CP 'A' JR C,ERROR1 CP 'Q' JR NC,ERROR1 SUB 'A' LD C,A ; Put in drive number INC IX RET ;..... ; ; GETUSR: LD A,(IX+0) CP '0' JR C,ERROR CP '9'+1 JR NC,ERROR SUB '0' ADD A,B LD B,A ; ; ; Adjust the byte in 'LENGTH' ; DRUS5: EX DE,HL ; Hl points to byte following ':' if any LD A,(LENGTH) ; Get length of move OR A ; Test it RET Z ; Return if null/ clear carry LD E,A LD A,5 SUB E LD (LENGTH),A OR A ; Clear any error RET ;..... ; ; ERROR1: POP DE ; Kill return address from subroutine ERROR: SCF ; Set error condition RET ;..... ; ; ; Get default user ; GETDFU: PUSH BC PUSH DE PUSH HL LD C,020H LD E,0FFH CALL SPBDOS POP HL POP DE POP BC LD B,A ; Set 'B' register to current user RET ;..... ; ; ; Get default drive ; GETDFD: PUSH BC PUSH DE PUSH HL LD C,19H CALL SPBDOS POP HL POP DE POP BC LD C,A ; Set 'C' register to current drive RET ;..... ; ; ; Extract token from command line and place it into DEFFCB; ; format DEFFCB FCB if token resembles file name and type ; (FILENAME.TYP); ; on input, CIBPTR points to character at which to start scan ; on output, CIBPTR points to character at which to continue ; and zero flag is reset if '?' is in token ; ; Entry points: ; scaner - load token into first FCB ; scanr1 - load token into FCB poibted to by HL ; ; SCANER: LD HL,DEFFCB ; Point to DEFFCB ; SCANR1: XOR A ; Set temporary drive number to default LD (TEMPDR),A CALL ADVNCE ; Skip to non-blank or end of line LD (CIPTR),DE ; Set pointer to non-blank or end of line LD A,(DE) OR A JR Z,SCANR2 SBC A,'A'-1 LD B,A INC DE LD A,(DE) CP ':' JR Z,SCANR3 DEC DE ; SCANR2: LD A,(TDRIVE) ; Set 1st byte of deffcb as default drive LD (HL),A JR SCANR4 ; SCANR3: LD A,B LD (TEMPDR),A LD (HL),B INC DE ; SCANR4: XOR A ; A=0 LD (QMCNT),A ; Init count of # of question marks in FCB LD B,8 ; Max of 8 characters in file name CALL SCANF ; Fill FCB file name ; ; ; Extract file type from possible FILENAME.TYP ; LD B,3 ; Prepare to extract type CP '.' ; If (de) delimiter is a '.', we have a type JR NZ,SCANR5 ; Fill file type bytes with INC DE ; Pt to char in command line after '.' CALL SCANF ; Fill FCB file type JR SCANR6 ; Skip to next processing ; SCANR5: CALL SCANF4 ; Space fill ; ; ; Fill in ex, s1, s2, and rc with zeroes ; SCANR6: LD B,4 ; 4 bytes ; SCANR7: INC HL ; Point to next byte in DEFFCB LD (HL),0 DJNZ SCANR7 ; ; ; Scan complete -- DE points to delimiter byte after token ; LD (CIBPTR),DE ; ; ; Set zero flag to indicate presence of '?' in FILENAME.TYP ; LD A,(QMCNT) ; Get number of question marks OR A ; Set zero flag to indicate any '?' RET ; ; ; Scan token pointed to by DE for a maximum of B bytes; place it into ; file name field pointed to by HL; expand and interpret wild cards of ; '*' and '?'; on exit, DE points to terminating delimiter ; SCANF: CALL SDELM ; Done if delimiter encountered - fill JR Z,SCANF4 INC HL ; Pt to next byte in deffcb CP '*' ; Is (de) a wild card? JR NZ,SCANF1 ; Continue if not LD (HL),'?' ; Place '?' in deffcb and dont advance de if so CALL SCQ ; Scanner count question marks JR SCANF2 ; SCANF1: LD (HL),A ; Store filename char in deffcb INC DE ; Pt to next char in command line CP '?' ; Check for question mark (wild) CALL Z,SCQ ; Scanner count question marks ; SCANF2: DJNZ SCANF ; Decrement char count until 8 elapsed ; SCANF3: CALL SDELM ; 8 chars or more - skip until delimiter RET Z ; Zero flag set if delimiter found INC DE ; Pt to next char in command line JR SCANF3 ; ; ; Fill memory pointed to by HL with spaces for B bytes ; SCANF4: INC HL ; Pt to next byte in deffcb LD (HL),' ' ; Fill filename part with DJNZ SCANF4 RET ;..... ; ; ; Increment question mark count for scanner - this routine increments ; the count of the number of question marks in the current FCB entry ; SCQ: LD A,(QMCNT) ; Get count INC A ; Increment LD (QMCNT),A ; Put count RET ;..... ; ; ; Protects the (IX) and (IY) values during BDOS calls ; SPBDOS: PUSH IX PUSH IY CALL BDOS POP IY POP IX RET ;..... ; ; ; Check to see if DE points to delimiter; if so, return with zero flag ; set. ; SDELM: LD A,(DE) OR A ; 0=delimiter RET Z CP ' ' ; Error if < RET Z ; =delimiter CP '=' ; '='=delimiter RET Z CP 5FH ; Underscore=delimiter RET Z CP '.' ; '.'=delimiter RET Z CP ':' ; ':'=delimiter RET Z CP ';' ; ';'=delimiter RET Z CP '<' ; '<'=delimiter RET Z CP '>' ; '>'=delimiter RET ;..... ; ; ; Advance input pointr to first non-blank and fall through to SBLANK ; ADVNCE: LD (CIBPTR),DE ; ; Skip string pointed to by DE (string ends in 0) until end of string ; or non-blank encountered (beginning of token) ; SBLANK: LD A,(DE) OR A RET Z CP ' ' RET NZ INC DE JR SBLANK ;..... ; ; ; Capitalize string (ending in 0) in cmdlin and set pointr for parsing ; CNVBUF: LD HL,CMDLIN+1 ; Point to users command LD B,(HL) ; Character count in 'B' INC B ; Add 1 in case of zero ; CNVBF1: INC HL ; Point to 1st valid character LD A,(HL) ; Capitalize command character CALL UCASE LD (HL),A DJNZ CNVBF1 ; Continue to end of command line ; CNVBF2: LD (HL),0 ; Store ending LD HL,CMDLIN+2 ; Set command line pointer to 1st char LD (CIBPTR),HL RET ;..... ; ; ; Convert character in 'A' to upper case ; UCASE: CP 61H ; Lower-case a RET C CP 7BH ; Greater than lower-case z? RET NC AND 5FH ; Capitalize RET ;..... ; ; GETOLD: CALL GETDFU ; Get current user into 'B' CALL GETDFD ; Get current drive into 'C' LD (OLDDRV),BC ; Get the parameters RET ;..... ; ; SETTMP: LD BC,(TMPDRV) JR RESET ;..... ; ; SETOLD: LD BC,(OLDDRV) JR RESET ;..... ; ; SETNEW: LD BC,(RQDDRV) ; Get the old drive number JR RESET ;..... ; ; SETCOM: LD BC,(COMDRV) ; Get the old drive number ; RESET: PUSH BC ; Save drive/user PUSH BC LD E,C ; Get selected drive LD C,14 ; Bdos function CALL SPBDOS POP BC ; Restore drive/user LD E,B ; Get selected user LD C,32 ; Bdis set user function CALL SPBDOS ; ; ; Set up byte at 0004h - some programs may look at it ; POP BC LD A,B ; Get user number RLA RLA RLA RLA AND 0F0H OR C LD (4),A RET ; DVUPR1: LD A,(TMPUSR) PUSH AF LD A,(TMPDRV) JR DVUPR3 ; DVUPRT: LD A,(RQDUSR) ; Get requested drive PUSH AF LD A,(RQDDRV) ; Get the requested user ; DVUPR3: ADD A,'A' CALL CTYPE ; Print the drive 'A'-'P' POP AF CP 10 ; Less that 10? JR C,DVUPR2 ; Yes - dont print the '1' PUSH AF LD A,'1' CALL CTYPE POP AF SUB 10 ; DVUPR2: ADD A,'0' CALL CTYPE LD A,':' JP CTYPE ;..... ; ; IF RCPM SUBFCB: DEFB 0 ; Use current drive DEFB '$$$ SUB' DEFB 0,0,0,0,0,0,0,0 ; Rest of the FCB DEFB 0,0,0,0,0,0,0,0 ; DEFB 0,0,0,0,0 DEFB 0,0,0,0 ; RFU ; ; ; Edit this to contain the console commands necessary to execute the ; logoff sequence for your system. ; BYECMD: DEFB 0 ; <====== do not touch DEFB 'BYE',CR,LF ; <====== put any number of cmds here DEFB 'Z'-40H ; <====== do not touch ; BYELEN EQU $-BYECMD-1 ENDIF ; RCPM ; ; ARCFLG: DEFB 0 DOADIR: DEFB 0 EXTFLG: DEFB 0 HLPCNT: DEFB 0 BIOS3: DEFW 0 TEMPDR: DEFB 0 CIPTR: DEFW 0 TDRIVE: DEFB 0 QMCNT: DEFB 0 CIBPTR: DEFW 0 TEMPHL: DEFW 0 LENGTH: DEFB 0 OLDDRV: DEFB 0 OLDUSR: DEFB 0 RQDDRV: DEFB 0 ; Requested drive RQDUSR: DEFB 0 ; Requested user COMDRV: DEFB 0 ; Drive to load .COM file COMUSR: DEFB 0 ; User to load .COM file TMPDRV: DEFB 0 ; Temporary drive number TMPUSR: DEFB 0 ; Temporary user number ACTIVE: DEFB 0 ; Attach command mode active NXTWRD: DEFW 0 DEFW 0 CMDLIN: DEFB 79 CMDLEN: DEFB 0 DEFS 79 DEFB 0 ; MEMBER: DEFB ' ' DEFB 0 DEFB 0 LBRNAM: DEFB ' ' ; Library file name DEFB 'LBR' ; TMPFCB: DEFS 36 DEFFCB: DEFS 36 ; DEFS 80 ; Area for stack ; STACK EQU $ ; ; END