; MDU.MAC -- sets maximum drive and user in ZCPR3 environment ; Vers equ 11 ; version number SubVers equ ' ' ; modification level ; ; USAGE: ; ; MDU {d}{u}{:} ; ; Set maximum drive and/or user in environment descriptor to the given ; value (A-P, 0-31). If no parameters are given, MDU displays current ; maximum drive and user. A following colon is optional. ; ; If the quiet flag is set, the current maximum DU will be displayed if ; MDU is called with no parameters; otherwise, only error messages will ; be displayed. If wheel byte is off, MAXDU will not be changed. ; ; If an out-of-range drive or user is given, the program error flag will ; be set to 2 (invalid directory). If the command line is invalid, the ; error flag will be set to 4 (unknown error). In either case the error ; handler will be invoked. ; ; Version 1.1 -- June 22, 1990 -- Gene Pizzetta ; Fixed bug that caused error handler to be invoked when quiet ; flag was set. (Thanks to Howard Goldstein.) Added wheel byte ; support. If wheel byte is reset, displays current maximum ; drive/user, but changes nothing. ; ; Version 1.0 -- June 17, 1990 -- Gene Pizzetta ; Original release. ; ; For bug reports and comments: ; Gene Pizzetta ; 481 Revere St. ; Revere, MA 02151 ; Voice: (617) 284-0891 ; Newton Centre Z-Node: (617) 965-7259 ; GEnie: E.PIZZETTA ; Bdos equ 05h CpmDma equ 80h LF equ 0Ah ; linefeed CR equ 0Dh ; carriage return ; MACLIB Z80 ; extended Intel mnemonics ; ; Following routines are from Z3LIB and SYSLIB, Version 4 ; ext epstr,pafdc,phl4hc,cout,isalpha,isdigit,eval10 ext z3init,getquiet,gzmtop,getmdisk,getmuser,getwhl ext putmdisk,putmuser,puter2,inverror,getefcb ; ; TYP3HDR.MAC, Version 1.1 -- Extended Intel Mnemonics ; This code has been modified as suggested by Charles Irvine so that it will ; function correctly with interrupts enabled. Extended Intel mnemonics by ; Gene Pizzetta, April 30, 1989. ; ; This is header code that can be used at the beginning of a type-3-environment ; program so that it will abort with an error message when not loaded to the ; correct address (such as when a user tries to run it under CP/M or Z30). ; entry: jr start0 ; Must use relative jump db 0 ; Filler db 'Z3ENV',3 ; Type-3 environment z3env: dw 0 ; Filled in by Z33 dw entry ; Intended load address ; start0: lxi h,0 ; Point to warmboot entry mov a,m ; Save the byte there di ; Protect against interrupts mvi m,0c9h ; Replace warmboot with a return opcode rst 0 ; Call address 0, pushing RETADDR onto stack retaddr: mov m,a ; Restore byte at 0 dcx sp ; Get stack pointer to point dcx sp ; ..to the value of RETADDR pop h ; Get it into HL and restore stack ei ; We can allow interrupts again lxi d,retaddr ; This is where we should be xra a ; Clear carry flag push h ; Save address again dsbc de ; Subtract -- we should have 0 now pop h ; Restore value of RETADDR jz start ; If addresses matched, begin real code ; lxi d,notz33msg-retaddr ; Offset to message dad d xchg ; Switch pointer to message into DE mvi c,9 jmp 0005h ; Return via BDOS print string function ; notz33msg: db 'Not Z33+$' ; Abort message if not Z33-compatible ; ; Messages . . . ; MsgUse: db 'MDU Version ' db Vers/10+'0','.',Vers mod 10+'0',SubVers db ' (loaded at ',0 MsgUs1: db 'h)',CR,LF db 'Usage:',CR,LF,' ',0 MsgNam: db 'MDU',0 MsgUs2: db ' {d}{u}{:}',CR,LF db 'Maximum drive and/or user are set to given values.',CR,LF db 'If no parameters are given, current maximum drive',CR,LF db 'and user are displayed.',0 MsgUs3: db CR,LF db 'Displays current maximum drive and user.',0 MsgMDU: db 'Maximum Drive and User: ',0 MsgIDr: db ' Invalid drive.',0 MsgIUr: db ' Invalid user.',0 MsgICL: db ' Invalid command line.',0 ; Start: lhld z3env ; set up environment call z3init sspd OldStk ; save old stack pointer call gzmtop ; get top of memory sphl ; ..and setup new stack ; xra a ; initialize data area sta Drive sta User lxi h,CpmDma ; point to command tail mov a,m ; get byte count ora a ; is there a tail? jrz ShowDU ; (no, so show current status) mov b,a inx h call EatSpc ; get past any spaces ora a ; at the end? jrz ShowDU ; (yes, so show current status) ani 7Fh cpi '/' ; request for help? jz Usage ; (yes) mov b,a ; save character call getwhl ; check wheel byte mov a,b ; get back character jrz QShwDU ; (it's reset, so don't do anything) ; call isalpha ; alphabetic character? jrnz GetNum ; (no, so check for digit) cpi 'Q' ; A-P? jrnc InvDrv ; (no, invalid drive) sta Drive ; store valid drive inx h ; advance pointer call EatSpc ; GetNum: ora a ; end of tail? jrz SetDrv ; (yes) cpi ':' ; colon? jrz SetDrv ; (yes) call isdigit ; is it a digit? jrnz InvCL ; (no, invalid command line) call eval10 ; evaluate number mov a,d ; check high byte ora a jrnz InvUsr ; (it's non-zero) mov a,e ; check low byte cpi 32 ; more than 31? jrnc InvUsr ; (yep) inr a ; add 1 to user sta User ; ..and store it mov a,m ; check next character cpi 0 ; null? jrz SetDrv ; (yes, end of tail) cpi ':' ; colon? jrz SetDrv ; (yes, it's okay) cpi ' ' ; trailing space? jrz SetDrv ; (yes, that's okay too) InvCL: mvi a,4 ; set error code lxi h,MsgICL ; say command line is bad jmp ErExit ; SetDrv: lda Drive ; get drive letter ora a ; do we have one? jrz SetUsr ; (no, so skip it) sui '@' ; make it binary call putmdisk ; ..and set maximum drive ; SetUsr: lda User ; get user (plus 1) ora a ; do we have one? jrz QShwDU ; (no, so skip it) dcr a ; decrement it call putmuser ; ..and set maximum user ; QShwDU: call getquiet ; check quiet flag jnz Finish ; (it's set) ShowDU: lxi h,MsgMDU call epstr call getmdisk ; get maximum drive adi '@' ; make it printable call cout ; ..and print it call getmuser ; get maximum user call pafdc ; ..and print it Finish: mvi a,0 ; set error code to zero jr Exit ; InvDrv: lxi h,MsgIDr ; say it's an invalid drive mvi a,2 ; set error code jr ErExit ; InvUsr: lxi h,MsgIUr ; say it's an invalid user number mvi a,2 ; set error code ; ErExit: call epstr ; print message Exit: call puter2 ; set error code mov b,a ; put error code in B ora a cnz inverror ; call error handler lspd OldStk ; restore old stack pointer ret ; ..and return to CCP ; ; Subroutines . . . ; ; EatSpc -- gobbles up spaces ; EatSpc: mov a,m cpi ' ' ; is it a space? inx h jrz EatSpc ; (yes) dcx h ret ; ; Print usage message ; Usage: lxi h,MsgUse ; print usage message call epstr lxi h,entry call phl4hc lxi h,MsgUs1 call epstr call ComNam ; print name we're called by, if possible call getwhl ; check wheel jrz Usage1 lxi h,MsgUs2 ; wheel byte set call epstr jmp Finish ; Usage1: lxi h,MsgUs3 ; wheel byte reset call epstr jmp Finish ; ; ComNam -- Print actual name by which this program was called, if available ; from external file control block. Otherwise, use "MDU". ; ComNam: call getefcb jrz NoEFcb ; (no external fcb) mvi b,8 ; print filename ComNLp: inx hl mov a,m ani 7Fh cpi ' ' cnz cout djnz ComNLp ret ; NoEFcb: lxi h,MsgNam ; print default name call epstr ret ; DSEG ; ; Uninitialized storage . . . ; Drive: ds 1 ; new maximum drive User: ds 1 ; new maximum user OldStk: ds 2 ; old stack pointer ; end