home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
rcpm
/
lux8080.ark
/
LUX43.MAC
< prev
next >
Wrap
Text File
|
1984-12-27
|
47KB
|
1,838 lines
;
; LUX - A Library extension system - Version 4.3 as of 12/27/84
;
; LUX Version 1.2B was Copyright 1983 by Steven R. Holtzclaw
; and entered into the public domain.
;
; 12-27-84 Modified MAKELUX.MAC, and LUX42.MAC creating LUX43.MAC
; LUX 4.3 and MKLX8080.ASM of which now will operate identically
; to the former LUX v4.2, but instead on any 8080 based
; system. Why this was not done earlier we know not why.
; - Donald Phillips
; - Douglas Coatney
; MicroBBS RCP/M (213) 598-8495
;
;
; 10-07-84 Changed extended command mode to be useable with NULU10
; LUX 4.2 instead of LU300's command structure. NULU is re-entrant
; and only needs to be loaded into memory for use.
; The extended commands are now "-L" to load NULU into the
; command mode and list the directory, or "-F" which loads
; NULU into the filesweep mode. From either mode, NULU is
; left in command mode until terminated. - [sls]
;
; 09-12-84 Added HARDCD equate for those of us supporting ZCPRs wheel
; LUX 4.1 but not using the maxdrv/maxusr values poked by ZCPR.
; Also added RCPM functions for TIME (TOS) and NEW (WHATSNEW)
; modules (impliment them as desired.) Also added CMDJMP
; equates for D and SD commands to work the same as DIR.
; Changed internal error-handling to point out command
; in error. - [sls]
;
; 09-07-84 Added auto-directory logic, added BYE function, with vector
; LUX 4.0 accessible from external program to force the removal of LUX.
; Removed system-specific and trivial textual code.
; Condensed revision info for quick reading. - [ mah ]
;
; Modification history in reverse order:
;
; [ srh ] - Steve R. Holtzclaw
; [ mah ] - Mark A. Howard CNY TECHNICAL RCP/M (315) 437-4890
; [ sls ] - Steve L. Sanders DATA COM NETWORK SYSTEMS (813) 937-3608
;
;
; 08/28/84 Elimination of external HELP system, message format mods. - [ sls ]
; LUX 3.0
;
; 02/04/84 Command formats changed, error messages changed. - [ sls ]
; LUX 2.2
;
; 01/23/84 Added LU internal calls, ZCPR, and EXTCMD logic. Reworked
; LUX 2.0 sone of the transients, and formatting changes. - [ mah ]
;
; 12/06/83 Added more code to test for altered BDOS/BIOS to eliminate
; LUX 1.2B problems with non-std systems. Dropped SD command. - [srh]
;
; 11/28/83 Make program self-relocating, works with BYELOW now. Error
; LUX 1.2A reporting bug fixed. - [ srh ]
;
; 11/26/83 Original release. Adapted from ATTACH program. - [ srh ]
;
;----------------------------------------------------------------------------
;
.Z80
;
TRUE EQU -1
FALSE EQU NOT TRUE
;
;----------------------------------------------------------------------------
;
; ====> This area must be edited for your configuration <====
;
; Also: if RCPM is true, edit BYECMD equate at end of file if
; your logoff program is NOT called BYE.COM
;
ZCPR EQU TRUE ; TRUE, if using nzcpr/zcmd/zcpr2/zcpr3
HARDCD EQU TRUE ; TRUE, use hard coded max values instead of
; ZCPR's max drive/max user
RCPM EQU TRUE ; TRUE, if being used with a RCP/M system
LUCMD EQU FALSE ; TRUE, if using NULU10 extended commands
HLPMSG EQU TRUE ; TRUE, if helpful messages are wanted
AUTODR EQU TRUE ; TRUE, if auto-dir wanted when LUX is
; first attached to a LBR file
HLPERS EQU 3 ; give auto-help after this many errors
;
; Note: if ZCPR and LUCMD are TRUE, extended commands
; will be disabled when WHEEL byte is reset (remote mode).
; If LUCMD is TRUE and ZCPR is FALSE, extended commands
; will always be enabled.
;
; The following equates define the drive and user number for each
; auxiliary lux module. (0=a, 1=b, etc)
;
TYPDRV EQU 0 ; drive number for type module
TYPUSR EQU 0 ; user number for type module
DIRDRV EQU 0 ; drive number for dir module
DIRUSR EQU 0 ; user number for dir module
;
;**********************************************************************
; note: The DIR.COM file must be a SD-xx.COM vers capable of $L option
;
FILDRV EQU 0 ; drive number for dir.com
FILUSR EQU 0 ; user number for dir.com
;**********************************************************************
;
CHKDRV EQU 0 ; drive number for chek module
CHKUSR EQU 0 ; user number for chek module
CRCDRV EQU 0 ; drive number for crck module
CRCUSR EQU 0 ; user number for crck module
;
; Note - the following are only necessary if RCPM is TRUE
;
CHTDRV EQU 0 ; drive number for chat.com
CHTUSR EQU 0 ; user number for chat.com
XMODRV EQU 0 ; drive number for xmodem module
XMOUSR EQU 0 ; user number for xmodem module
TIMDRV EQU 0 ; drive number for time.com
TIMUSR EQU 0 ; user number for time.com
NEWDRV EQU 0 ; drive number for new.com
NEWUSR EQU 0 ; user number for new.com
;
; Note - the following is only necessary if LUCMD is TRUE
;
; Designed for use with the new NULU10 utility, looks for
; the file called NULU.COM not LU300.COM
;
LUDRV EQU 0 ; drive number for NULU.com
LUUSR EQU 15 ; user number for NULU.com
;
;----------------------------------------------------------------------------
;
VERS EQU 43 ; version number
MODLVL EQU ' ' ; modification level
BDOS EQU 0005H
TPA EQU 0100H ; cpm program area
FCB1 EQU 005CH ; first file control block
FCB2 EQU 006CH ; second file control block
REBOOT EQU 0000H ;
CBUFF EQU 080H ; default command buffer
;
IF HARDCD
MAXDRV EQU 6 ; max drive (0-15) 0=a: 1=b:, etc...
MAXUSR EQU 14 ; max user area (0-31)
ENDIF
;
ZPRDRV EQU 03DH ; zcpr max drive location
ZPRUSR EQU 03FH ; zcpr max user location
WHEEL EQU 03EH ; zcpr wheel byte location
;
; 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
DEFB USERN1+'0'
DEFB ':'
DEFB FNCNAM
DEFB 0
IF NOT NUL RTN1
CALL RTN1
ENDIF
IF NOT NUL RTN2
CALL RTN2
ENDIF
IF NOT NUL RTN3
CALL RTN3
ENDIF
IF NOT NUL RTN4
CALL RTN4
ENDIF
JP PROCES
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
DEFB USERN2+'0'
DEFB ':'
DEFB FNCNAM
DEFB 0
ENDM
;
CMDJMP MACRO VERB,VECTOR
CALL ILCMP
DEFB VERB
DEFB 0
JP NC,VECTOR
ENDM
;
START EQU $
LD SP,SSTACK ; starting stack
CALL ILPRT
DEFB 13,10,'LUX v'
DEFB (VERS/10)+'0'
DEFB '.'
DEFB (VERS MOD 10)+'0',MODLVL
DEFB ' as of 27-Dec-84',13,10,0
;
; set up max drive/user
;
IF HARDCD ; if HARDCD true, use spec'd values
LD A,MAXDRV ; hard coded max drive
LD (DRVMAX),A
LD A,MAXUSR ; hard coded max user
LD (USRMAX),A
ELSE
LD A,(ZPRDRV) ; if not HARDCD, use ZCPR maximums
LD (DRVMAX),A ; max drive
LD A,(ZPRUSR) ; max user
DEC A
LD (USRMAX),A
ENDIF
;
; check for a blank or null command line
;
LD A,(CBUFF+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 13,10
;
DEFB '++ Examples of valid LUX commands ++',13,10
DEFB 13,10
DEFB ' LUX FILENAME <-Attach to FILENAME.LBR'
DEFB ' on current drive/user',13,10
DEFB ' LUX A4:FILENAME <-Attach to FILENAME.LBR'
DEFB ' on drive A:- USER 4',13,10
DEFB ' LUX B1:FILENAME <-Attach to FILENAME.LBR'
DEFB ' on drive B:- USER 1',13,10
DEFB 13,10
DEFB ' FILENAME must be a valid library (.LBR) file',13,10
DEFB 0
JP REBOOT ; reboot since we have destroyed the ccp
;
BDDRUS: CALL ILPRT
DEFB 13,10
DEFB '++ Invalid drive/user number ++',7,13,10,0
JP SPCERR
;
;
GTDVUS: LD HL,CBUFF+2 ; index default key buffer
CALL DRUSR ; get requested drive/user
JP C,SPCERR
;
; test for drive/user within range
;
PUSH HL ; save command line pointer
PUSH BC ; save drive/user spec
LD A,(DRVMAX) ; get max drive
CP C
JP C,BDDRUS
LD A,(USRMAX)
CP B
JP C,BDDRUS
POP HL
LD (RQDDRV),HL ; set the requested drive/user
POP HL
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 HL,'BL' ; set 'LB' into first two bytes of file type
LD (FCB1+9),HL
LD A,'R' ; set 'R' into last byte of file type
LD (FCB1+11),A
;
; get the library name from the fcb and store it
;
LD HL,FCB1 ; source for move
LD DE,LBRNAM-1 ; destination for move
LD BC,9 ; max 8 character filename
TMP010: LD A,(HL)
INC HL
EX DE,HL
LD (HL),A
INC HL
EX DE,HL
DEC C
JP NZ,TMP010 ; LDIR replacement
; LDIR ; move to local name
;
AMBTST: LD HL,FCB1+1 ; first byte of filename
LD A,'?' ; character to look for
LD BC,11 ; search thru 11 bytes
TMP110: CP (HL)
PUSH AF
INC HL
DEC C
JP NZ,TMP112
POP AF
JP TMP115
TMP112: POP AF
JP NZ,TMP110
TMP115 EQU $
; CPIR ; do search
JP NZ,LOOKUP ; no ? found - continue
;
NOAMBG: CALL ILPRT ; print the error message
DEFB 13,10
DEFB '++ Ambiguous filenames are not allowed ++',7,13,10,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 BDOS ; set the dma address
LD DE,FCB1 ; index filename specified
LD C,17
CALL BDOS ; search for first
INC A ; does file exist?
JP NZ,PGMSTR ; jump to start of lux
;
NOFILE: CALL SETOLD
CALL ILPRT ; print the error message
DEFB 13,10,'Can''t find ',0
CALL DVUPRT
CALL NAMPRT ; print the filename
CALL ILPRT
DEFB ' - check the DIR',7,13,10,0
JP 0 ; 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 V4.20' ; the name 'LUX' is a clue to other
; programs that enables them to determine
; 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,80h ; bytes to clear
XOR A ;
RZRLP: LD (DE),A ;
INC DE ;
DEC B
JP NZ,RZRLP ; DJNZ replacement
; DJNZ RZRLP ;
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 addr
LD BC,BYELEN ;
TMP020: LD A,(HL)
INC HL
EX DE,HL
LD (HL),A
INC HL
EX DE,HL
DEC C
JP NZ,TMP020 ; LDIR replacement
; LDIR ;
POP DE ; restore it again
LD C,26 ; reset the DMA
CALL BDOS ;
LD DE,SUBFCB ; address the .SUB file FCB
LD C,22 ; make the file
CALL BDOS ;
INC A ; check for errors
JP Z,EXITER ; oooops, no dir space
LD DE,SUBFCB ; else write the data
LD C,21 ;
CALL BDOS ;
INC A ;
JP Z,EXITER ; oooops, no space left
LD DE,SUBFCB ;
LD C,16 ; now close the file
CALL BDOS ;
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 ; we had an error trying to make the .sub file
DB 13,10,7,'+ Error: Can''t remove LUX! Please +'
DB 13,10,'+ type CTRL-C to exit LUX, +'
DB 13,10,'+ then type BYE to logoff. +',0
LD SP,STACK ;
JP GETCMD ;
;
ENDIF ;RCPM
;
; this is the LUX intialization
;
INIT: LD HL,(1) ; get warm boot vector
LD (BIOS3),HL ; save old warm boot vector
LD HL,(6) ; get bdos start
LD (PGMSTR+1),HL ; set new jump to bdos
LD HL,PGMSTR ; get local bdos vector
LD (6),HL ; set it in low memory
LD SP,STACK ; reset stack
;
; save the old bios vectors
;
LD HL,(BIOS3) ; bios wboot address
LD DE,OWBOOT ; local wboot address
LD BC,12 ; 12 bytes to move
TMP030: LD A,(HL)
INC HL
EX DE,HL
LD (HL),A
INC HL
EX DE,HL
DEC C
JP NZ,TMP030 ; LDIR replacement
; LDIR ; move the block
;
; set up the new bios vectors
;
LD DE,WBOOT ; source is local table
LD HL,(BIOS3) ; destination is old bios
EX DE,HL
LD BC,12 ; 12 bytes to move
TMP040: LD A,(HL)
INC HL
EX DE,HL
LD (HL),A
INC HL
EX DE,HL
DEC C
JP NZ,TMP040 ; LDIR replacement
; LDIR ; move the block
;
LD A,0FFH ; set the auto-dir 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 vconin
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 3 ; control c ?
RET NZ ; nope - let bios have it
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 'CTRL-C entered',13,10,13,10 ; dummy printout
DEFB ' >> exiting LUX - standby',0
;
UNPATH: LD DE,OWBOOT ; index old warm boot vector
LD HL,(BIOS3) ; bios jump table
EX DE,HL
LD BC,12 ; 12 bytes to move
TMP050: LD A,(HL)
INC HL
EX DE,HL
LD (HL),A
INC HL
EX DE,HL
DEC C
JP NZ,TMP050 ; LDIR replacement
; LDIR ; move the old table back
CALL SETOLD ; set old drive/user
JP 0 ; 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
JP 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,CBUFF+1 ; place to put command string
LD HL,CBUFF+1
LD (CPTRIX),HL
; LD IY,CBUFF+0 ; length of command
XOR A
; LD (IY+0),A
LD (CBUFF),A
;
IF AUTODR
;
LD A,(DOADIR) ; shall we do a directory?
OR A ;
JP 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 13,10,'[ in LUX CTRL-C to exit, HELP for menu ]',13,10,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 BDOS ; read console buffer
LD A,(CMDLEN) ; get command length
OR A ; test it
JP 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
;
GETCM4: LD DE,CMDLIN+2 ; index data from the command line
;
CMDJMP 'HELP',QKHELP ; quick help summary
CMDJMP '?',QKHELP ; alternate for HELP
CMDJMP 'TYPE',TIPE ; file type command process
CMDJMP 'DIR',DIR ; dir command process
CMDJMP 'D',DIR ; alternate for DIR
CMDJMP 'SD',DIR ; alternate for DIR
CMDJMP 'LUX',LUX ; lux command process
CMDJMP 'FILES',FILES ; run dir.com in "*.lbr" mode
CMDJMP 'CHEK',CHEK ; run lchek
CMDJMP 'CRCK',CRCK ; run lcrck
;
IF RCPM
;
CMDJMP 'XMODEM',XMODEM ; xmodem command process
CMDJMP 'SEND',SEND ; synonym for XMODEM S
CMDJMP 'CHAT',CHAT ; signal operator with chat.com
CMDJMP 'BYE',REMOVE ; remove LUX, and run BYE
CMDJMP 'TIME',TIME ; display timeon/current time
CMDJMP 'TOS',TIME ; alternate for TIME
CMDJMP 'NEW',NEW ; display new files list
CMDJMP 'WHATSNEW',NEW ; alternate for NEW
;
ENDIF ;RCPM
;
IF ZCPR AND LUCMD AND RCPM
;
LD A,(WHEEL) ; check the wheel byte
OR A ;
JP Z,CMDERR ; don't allow SYSOP cmds if remote
;
ENDIF ;ZCPR AND LUCMD AND RCPM
;
IF LUCMD ; extended LU commands
;
CMDJMP '-L',LOAD ; load NULU in command mode and display dir
;
CMDJMP '-F',FSWP ; load NULU in filesweep mode
;
ENDIF ;LUCMD
;
CMDERR: CALL ILPRT
;
; this will actually print the command in error like this
;
; ERROR --> dur <-- is not a valid LUX command.
;
DEFB 13,10,13,10,'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) ;
JP 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.',7,13,10,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 ?
JP Z,GETCM6 ; yes - dont print it
CP 000H ; null
JP Z,GETCM6 ; yes - all done
CALL CTYPE ; print the character
INC HL ; next character
DEC B
JP NZ,GETCM5 ; DJNZ replacement
; 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
;
;
TIPE: DRVUSR TYPDRV,TYPUSR,'LUXTYP ',FILNAM,FILSPC,FILMEM,NULL
;
DIR: DRVUSR DIRDRV,DIRUSR,'LUXDIR ',FILNAM,FILSPC,FILMEM,NULL
;
FILES: DRVUSR FILDRV,FILUSR,'DIR *.LBR',NULL,NULL,NULL,NULL
;
CHEK: DRVUSR CHKDRV,CHKUSR,'LUXCHK ',FILNAM,FILSPC,FILMEM,NULL
;
CRCK: DRVUSR CRCDRV,CRCUSR,'LUXCRC ',FILNAM,FILSPC,FILMEM,NULL
;
IF RCPM
;
SEND: DRVUSR XMODRV,XMOUSR,'XMODEM L ',FILNAM,FILSPC,FILMEM,NULL
;
CHAT: DRVUSR CHTDRV,CHTUSR,'CHAT',NULL,NULL,NULL,NULL
;
TIME: DRVUSR TIMDRV,TIMUSR,'TIME',NULL,NULL,NULL,NULL
;
NEW: DRVUSR NEWDRV,NEWUSR,'NEW',NULL,NULL,NULL,NULL
;
ENDIF ; RCPM
;
IF LUCMD ;
;
LOAD: DVUS LUDRV,LUUSR,'NULU -O ',NULL,NULL,NULL,NULL
CALL FILNAM ;
CALL FILTYP ; * load NULU in command mode *
DEFB ' -L',0 ; * and display the directory *
JP PROCES ;
;
FSWP: DVUS LUDRV,LUUSR,'NULU -O ',NULL,NULL,NULL,NULL
CALL FILNAM
CALL FILTYP
DEFB ' -F',0 ; * load NULU in filesweep mode *
JP PROCES
;
; parse the ambiguous user/drive spec & filename, and place in command line
;
AFNPRS: CALL FNDSPC ; find the first space
JP C,CMDERR ; error if all scanned and no space
CALL ADVANC ; advance to next non-blank
JP C,CMDERR ; premature eol is error
; PUSH IX ; drusr uses this ...
CALL DRUSR ; get drive/user, if any
; POP IX ;
OR A ; did drive/user change?
JP Z,SKPDVU ;
PUSH BC ; skip over the drive spec in cmd line
LD B,A ; get bytes to skip
LD HL,NXTWRD ; address cmd pointer
SKPTR: INC (HL) ;
DEC B
JP NZ,SKPTR ; DJNZ replacement
; DJNZ SKPTR ;
POP BC ; restore user/drive spec
CALL BDSDVU ; convert to BDS usr/drv
JP C,BDDRUS ; if cy, then limits exceeded
SKPDVU: CALL FILMEM ; the rest is normal stuff
JP PROCES ;
;
ENDIF ;LUCMD
;
; quick help summary
;
QKHELP: CALL ILPRT
;
DEFB 13,10,13,10
DEFB 'You are presently attached to a library file with the',13,10
DEFB 'LUX utility. These are the available commands:',13,10,10
DEFB 'LUX filename - Attach to another LBR file ',13,10
DEFB 'LUX du:filename - Attach to LBR file on specified du:',13,10
DEFB 'DIR, D, or SD - Display attached library members',13,10
DEFB 'FILES - Display other .LBR files on this du:',13,10
DEFB 'TYPE filename.typ- Display ASCII file contents',13,10
DEFB 'CHEK filename.typ- Run CHEK on requested member',13,10
DEFB 'CRCK filename.typ- Run CRCK on requested member',13,10
;
IF RCPM
;
DEFB 'SEND filename.typ- Sends a library member file',13,10
DEFB 'XMODEM S filename.typ- Same as SEND command',13,10
DEFB 'CHAT - Chat with SYSOP (if available)',13,10
DEFB 'BYE - logs off the system',13,10
DEFB 'TIME (TOS) - Displays timeon and current time',13,10
DEFB 'NEW (WHATSNEW) - List of new files on-line',13,10
;
ENDIF ; RCPM
;
DEFB 'HELP - Displays this menu',13,10
;
IF NOT HLPMSG
;
DEFB 13,10,'[ in LUX CTRL-C to exit, HELP for menu ]',13,10
;
ENDIF ; NOT HLPMSG
;
DEFB 0
;
IF LUCMD AND ZCPR AND RCPM
;
LD A,(WHEEL) ; should we display extended commands?
OR A ;
JP Z,GETCMD ; if wheel byte is reset, no
;
ENDIF ;LUCMD AND ZCPR AND RCPM
;
IF LUCMD
;
CALL ILPRT ;
DEFB 13,10,'[Hit any key] ',0
LD C,1
CALL BDOS ;
CALL CRLF ;
CALL CRLF ;
CALL ILPRT ;
DEFB 13,10
DEFB 'NULU Extended Commands',13,10
DEFB '======================',13,10,13,10
DEFB '-L NULU command mode and display DIR',13,10
DEFB '-F NULU filesweep mode',13,10,13,10
DEFB 'NULU is re-entrant and only needs to',13,10
DEFB 'loaded into memory. All commands may',13,10
DEFB 'be listed with -M command once loaded.',13,10,13,10
DEFB 0
;
ENDIF ;LUCMD
;
JP GETCMD
;
; xmodem is a special case since the 'R' and 'L' options
; are invalid here
;
IF RCPM
;
XMODEM: CALL ADVANC ; go to next character
LD A,(HL) ; get the character
CP 'S' ; not legal here
JP Z,XMODE1 ; ok to continue
CP 'R' ; not legal here
JP Z,XMODE2 ; execute error routine
CP 'L' ; not legal here
JP Z,XMODE3 ; execute error routine
DRVUSR XMODRV,XMOUSR,'XMODEM',NULL,NULL,NULL,NULL
;
XMODE1: CALL NXTSPC ; look for next space
JP SEND
;
XMODE2: CALL CRLF
CALL PRTERR ; print the command
CALL ILPRT ; print the following
DEFB ' can''t (R)eceive while in LUX',7,13,10,0
JP GETCMD ; return to command
XMODE3: CALL CRLF
CALL PRTERR ; print the command
CALL ILPRT ; print the following
DEFB ' only uses (S)end command while in LUX',7,13,10,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
PUSH BC ; save drive/user spec
PUSH HL ; save command line pointer
LD H,B
LD L,C
LD (TMPDRV),HL ; save the temporary drive/user
LD A,(DRVMAX) ; get max drive
CP C
JP C,LUX03 ; if out of range
LD A,(USRMAX)
CP B
JP C,LUX03 ; if out of range
POP HL
POP BC
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
JP Z,LUX05 ; ...error - file not found
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,8 ; 8 character file name
TMP060: LD A,(HL)
INC HL
EX DE,HL
LD (HL),A
INC HL
EX DE,HL
DEC C
JP NZ,TMP060 ; LDIR replacement
; LDIR ; move it
CALL ILPRT ; for display neatness
DEFB 13,10,0 ;
LD A,0FFH ; set the auto-directory flag
LD (DOADIR),A ;
JP GETCMD ;
;
LUX03: POP HL
POP BC
LUX04: CALL ILPRT
DEFB 13,10,'++ Invalid drive/user number ++',7,13,10,0
JP GETCMD
;
LUX05: CALL ILPRT
DEFB 13,10,10,'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',7,13,10,0
JP GETCMD
;
PROCES: XOR A ; zero last byte of new command line
; LD (IX+0),A
LD HL,(CPTRIX)
LD (HL),A
LD HL,CBUFF+1
LD (HLPCNT),A ; reset the error count
CALL DRUSR ; get drive/user
; LD (COMDRV),BC ; set the com drive/user
PUSH HL
LD H,B
LD L,C
LD (COMDRV),HL
POP HL
EX DE,HL ; de is source address to create new fcb
CALL SCANER ; create the new fcb
EX DE,HL ; into 'HL'
LD DE,CBUFF+1 ; start of command buffer
PUSH HL
PUSH DE
OR A ; clear any cy
LD A,H
SBC A,D
LD H,A
LD A,L
SBC A,E
LD L,A ; Replace SBC HL,DE
; SBC HL,DE ; calculate length of move
LD A,(CBUFF) ; get command line length
SUB L ; calculate new length
LD (CBUFF),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
TMP070: LD A,(HL)
INC HL
EX DE,HL
LD (HL),A
INC HL
EX DE,HL
DEC C
JP NZ,TMP070 ; LDIR replacement
; LDIR ; move the block down
LD HL,FCB1 ; set up first fcb
LD DE,CBUFF+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
; the extent number
LD (DEFFCB+15),A
LD (DEFFCB+32),A
CALL SETCOM ; set com drive/user
;
LD DE,TPA
LD C,01AH
CALL BDOS ; set dma to tpa
;
LD DE,DEFFCB
LD C,011H
CALL BDOS ; search for first
INC A
JP NZ,PROCE1 ; file found
;
CALL ILPRT
DEFB 13,10,'Can''t find ',0
LD B,8
LD HL,DEFFCB+1
CALL NAMPR1 ; print the file name
CALL ILPRT ; cr/lf
DEFB 7,13,10,0
JP ENTRY ; go for more commands
;
PROCE1: LD DE,TPA
LD C,01AH
CALL BDOS ; set dma to tpa
;
LD DE,DEFFCB
LD C,00FH
CALL BDOS ; open file
INC A
JP NZ,PROCE2
;
CALL ILPRT
DEFB 13,10,'.COM File error - notify SYSOP',7,7,13,10,0
JP ENTRY
;
; load the .com file into memory @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 BDOS ; set dma
LD DE,DEFFCB ; index .com file name
LD C,014H
CALL BDOS ; read a record
POP HL ; restore 'DE' and 'HL'
POP DE
EX DE,HL ; 'HL' is dma address again
OR A ; end of file ?
JP Z,LODCOM ; no - read another record
;
LD C,13
CALL BDOS ; 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
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?
JP Z,NAMPR2 ; yes - dont print
CALL CTYPE ; else print the character
NAMPR2: INC HL ; next character
DEC B
JP NZ,NAMPR1 ; DJNZ replacement
; 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
DEC B
JP NZ,NAMPR3 ; DJNZ replacement
; 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
JP Z,ILPRT2 ; null - end of string
CALL CTYPE ; else type the character
INC HL ; next character
JP 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
JP Z,FILTY2
CALL PUTIN
INC HL
JP FILTY1
FILTY2: EX (SP),HL
RET
;
; fill command line with a space
;
FILSPC: LD A,020H ; space character
CALL PUTIN ; fill in
RET
;
; 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 ?
JP Z,FILNA2 ; yes - dont add to command line
CALL PUTIN ; put character into command line
FILNA2: INC HL ; next character
DEC B
JP NZ,FILNA1 ; DJNZ replacement
; 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
DEC B
JP NZ,FILNA3 ; DJNZ replacement
; 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
DEC B
JP NZ,FILME1 ; DJNZ replacement
; DJNZ FILME1 ; continue looping
RET ; done
;
;PUTIN: LD (IX+0),A ; stuff the character into command line
; INC IX ; get ready for next character
PUTIN: PUSH HL
LD HL,(CPTRIX)
LD (HL),A
INC HL
LD (CPTRIX),HL
; INC (IY+0) ; bump command line length
LD HL,CBUFF
INC (HL)
POP HL
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
DEC B
JP NZ,PARSE1 ; DJNZ replacement
; 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
JP PARSE2 ; continue looping
;
; advanc - advance the word at nxtwrd to the next non blank address
; of the command 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
JP Z,ADVAN3 ; error - null character
CP 020H ; space ?
JP NZ,ADVAN2 ; yes - done
INC HL
LD (NXTWRD),HL ; put pointer back
JP 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
JP FND01 ; else continue the search
FNDER: SCF ; all characters 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?
JP Z,NXTSP2 ; ...yes - return
CP 020H ; if at a space?
JP Z,NXTSP2 ; ...yes - return
INC HL ; next character
JP 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
JP Z,SAME1 ; yes - same so far - test next char
LD A,(DE) ; get a byte from command string
CP (HL) ; same as source
JP NZ,NOTSAM ; no - not the same
INC HL ; next source
INC DE ; next compare
JP ILCMP1 ; loop again
NOTSAM: XOR A ; zero for the test
NSLP: INC HL ; next immediate byte
CP (HL) ; null yet ?
JP 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 ?
JP Z,SAME ; yes - its ok
CP 020H ; space ?
JP Z,SAME ; yes - thats ok too...
JP SAME2 ; not ok- must be another character
;
CTYPE: PUSH AF ; save all registers
PUSH BC
PUSH DE
PUSH HL
AND 07FH ; be sure its ascii
LD E,A ; into 'E'
LD C,2 ; cpm console function
CALL BDOS
POP HL ; restore all registers
POP DE
POP BC
POP AF
RET ; return to caller
;
CRLF: LD A,13
CALL CTYPE
LD A,10
JP 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 (CPTRIX),HL
LD BC,5 ;
LD A,':'
TMP120: CP (HL)
PUSH AF
INC HL
DEC C
JP NZ,TMP122
POP AF
JP TMP125
TMP122: POP AF
JP NZ,TMP120
TMP125 EQU $
; 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)
PUSH HL
LD HL,(CPTRIX)
LD A,(HL)
POP HL
CP '0'
JP C,ERROR
CP '9'+1
JP 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
SLA A ; * 2
SLA A ; * 4
ADD A,B ; + b (* 5)
SLA A ; * 10
LD B,A
; INC IX ; skip the tens digit
PUSH HL
LD HL,(CPTRIX)
INC HL
LD (CPTRIX),HL
POP HL
JP GETUSR ; get the user number
;
; format was - du:filename.ext
;
DRUS2: CALL GETDRV ; get the drive parameter
JP 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: JP DRUS5
;
;GETDRV: LD A,(IX+0)
GETDRV: PUSH HL
LD HL,(CPTRIX)
LD A,(HL)
POP HL
CP 'A'
JP C,ERROR1
CP 'Q'
JP NC,ERROR1
SUB 'A'
LD C,A ; put in drive number
; INC IX
PUSH HL
LD HL,(CPTRIX)
INC HL
LD (CPTRIX),HL
POP HL
RET
;
;GETUSR: LD A,(IX+0)
GETUSR: PUSH HL
LD HL,(CPTRIX)
LD A,(HL)
POP HL
CP '0'
JP C,ERROR
CP '9'+1
JP 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 BDOS
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,019H
CALL BDOS
POP HL
POP DE
POP BC
LD C,A ; set 'C' register to current drive
RET
;
; convert the drive/user bytes in BC to a BDS-C user/drive specification
; and place in command line
;
BDSDVU: PUSH BC ; save drive/user spec
PUSH HL ; save command line pointer
LD A,(DRVMAX) ; check for max's exceeded
CP C ;
JP C,DUERR ;
LD A,(USRMAX) ;
CP B ;
JP C,DUERR ;
POP HL ;
POP BC ;
LD A,B ; get the user number
CP 10 ; is it less than 10?
JP C,BDS2 ; yes, don't insert the '1'
LD A,'1' ;
CALL PUTIN ;
LD A,B ; reget the user number
SUB 10 ; subtract 10
BDS2: ADD A,'0' ; add in ascii bias
CALL PUTIN ;
LD A,'/' ; now the stupid bds-c slash
CALL PUTIN ;
LD A,C ; get the drive number
ADD A,'A' ; add ascii bias
CALL PUTIN ;
LD A,':' ;
CALL PUTIN ;
XOR A ; to indicate successfullness
RET ;
;
DUERR: POP HL ; justify the stack
POP BC
SCF ; error flag
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 pts to char at which to start scan;
; on output, cibptr pts to char 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 pted 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 ptr to non-blank or end of line
EX DE,HL
LD (CIPTR),HL
EX DE,HL
LD A,(DE)
OR A
JP Z,SCANR2
SBC A,'A'-1
LD B,A
INC DE
LD A,(DE)
CP ':'
JP Z,SCANR3
DEC DE
SCANR2: LD A,(TDRIVE) ; set 1st byte of deffcb as default drive
LD (HL),A
JP SCANR4
SCANR3: LD A,B
LD (TEMPDR),A
LD (HL),B
INC DE
SCANR4: XOR A ; a=0
LD (QMCNT),A ; init count of number of question marks in fcb
LD B,8 ; max of 8 chars 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
JP NZ,SCANR5 ; fill file type bytes with <sp>
INC DE ; pt to char in command line after '.'
CALL SCANF ; fill fcb file type
JP 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 ; pt to next byte in deffcb
LD (HL),0
DEC B
JP NZ,SCANR7 ; DJNZ replacement
; DJNZ SCANR7
;
; scan complete -- de pts to delimiter byte after token
;
; LD (CIBPTR),DE
EX DE,HL
LD (CIBPTR),HL
EX DE,HL
;
; 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
;
; scanf -- scan token pted to by de for a max of b bytes; place it into
; file name field pted to by hl; expand and interpret wild cards of
; '*' and '?'; on exit, de pts to terminating delimiter
;
SCANF: CALL SDELM ; done if delimiter encountered - <sp> fill
JP Z,SCANF4
INC HL ; pt to next byte in deffcb
CP '*' ; is (de) a wild card?
JP NZ,SCANF1 ; continue if not
LD (HL),'?' ; place '?' in deffcb and dont advance de if so
CALL SCQ ; scanner count question marks
JP 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: DEC B
JP NZ,SCANF ; DJNZ replacement
; 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
JP 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 <sp>
DEC B
JP NZ,SCANF4 ; DJNZ replacement
; 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
;
; check to see if de pts to delimiter; if so, ret w/zero flag set
;
SDELM: LD A,(DE)
OR A ; 0=delimiter
RET Z
CP ' ' ; error if < <sp>
RET Z ; <sp>=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 ptr to first non-blank and fall through to sblank
;
;ADVNCE: LD (CIBPTR),DE
ADVNCE: EX DE,HL
LD (CIBPTR),HL
EX DE,HL
;
; skip string pted 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
JP SBLANK
;
;
; capitalize string (ending in 0) in cmdlin and set ptr for parsing
;
CNVBUF: LD HL,CMDLIN+1 ; pt to users command
LD B,(HL) ; char count in b
INC B ; add 1 in case of zero
CNVBF1: INC HL ; pt to 1st valid char
LD A,(HL) ; capitalize command char
CALL UCASE
LD (HL),A
DEC B
JP NZ,CNVBF1 ; DJNZ replacement
; DJNZ CNVBF1 ; continue to end of command line
CNVBF2: LD (HL),0 ; store ending <null>
LD HL,CMDLIN+2 ; set command line ptr to 1st char
LD (CIBPTR),HL
RET
;
; convert char 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 driv into 'C'
; LD (OLDDRV),BC ; get the parameters
PUSH HL
LD H,B
LD L,C
LD (OLDDRV),HL
POP HL
RET
;
;SETTMP: LD BC,(TMPDRV)
SETTMP: PUSH HL
LD HL,(TMPDRV)
LD B,H
LD C,L
POP HL
JP RESET
;
;SETOLD: LD BC,(OLDDRV)
SETOLD: PUSH HL
LD HL,(OLDDRV)
LD B,H
LD C,L
POP HL
JP RESET
;
;SETNEW: LD BC,(RQDDRV) ; get the old drive number
SETNEW: PUSH HL
LD HL,(RQDDRV)
LD B,H
LD C,L
POP HL
JP RESET
;
;SETCOM: LD BC,(COMDRV) ; get the old drive number
SETCOM: PUSH HL
LD HL,(COMDRV)
LD B,H
LD C,L
POP HL
;
RESET: PUSH BC ; save drive/user
PUSH BC
LD E,C ; get selected drive
LD C,14 ; bdos function
CALL BDOS
POP BC ; restore drive/user
LD E,B ; get selected user
LD C,32 ; bdis set user function
CALL BDOS
;
; set up byte at 4h - 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)
JP 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?
JP 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
;
NULL: RET
;
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
;
'BYE',13,10 ;<====== put any number of cmds here
;
DEFB 'Z'-40H ;<====== do not touch
;
BYELEN EQU $-BYECMD-1
;
ENDIF ;RCPM
;
DOADIR: DEFB 0
HLPCNT: DEFB 0
BIOS3: DEFW 0
DRVMAX: DEFB 0
USRMAX: DEFB 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'
;
CPTRIX: DEFS 2 ;<IX> points to Command line
;
TMPFCB: DEFS 36
DEFFCB: DEFS 36
DEFS 80
STACK EQU $
;
;
END