; RPASS14.Z80 Remote System Utility for BYE5xx 26 Dec 86 ; ; This program enables viewing or changing high memory bytes in ; the BYE5xx program, and/or the Page 0 bytes (wheel, max drive, ; max user, iobyte, etc.). ; ; Following are formats for usage, entered at the CP/M command line: ; ; RPASS I <<-- set/view iobyte (CP/M 1.x or 2.x) ; RPASS B <<-- next menu (if BYE active) ; RPASS R <<-- max remote values, wheel reset ; RPASS S <<-- max system values ; RPASS W <<-- set wheel byte ; RPASS <<-- first menu (default) ; ; To use, enter one of the above commands. If BYE is active, you will ; be prompted for the correct password. If incorrect, you will return ; to CP/M. If an option was given and the password is correct, the ; function will be performed, then the menu will appear. If NO option ; was given and the password is correct then just the menu will appear. ; The password does not echo to the console, thus maintaining security ; should the program be used while a remote user is on-line. ; ; This is a Public Domain program. It may not be sold in whole or part ; as is the case for many public domain programs. If any improvements ; are made to the program, increment the version number and upload the ; new version to CompuServe CP/M Sig. ; G.F.Reding [72436,45] ; ;-------------------------------------------------------------- ; ; 26 Dec 86 Some changes made to add options, to improve ; v 1.4 speed (z80 code), deletion of Hayes Chronograph ; clock set routine, etc. ; ; 14 Dec 85 Version upgraded G.F.Reding ; v 1.3 Added page 0 options which were ; not included in v1.2. ; ; 08 Oct 85 Version upgraded G.F.Reding ; v 1.2 For use with the BYE5xx series ; ; 13 Apr 85 Original version G.F.Reding ; v 1.1 Enabled manipulation of page 0 bytes, ; Hayes Chronograph clock setting, etc. ; ;-------------------------------------------------------------- ; NO EQU 0 ; For conditional assembly YES EQU NOT NO ; VERS EQU 14 ; Program vers number ; ; BDOS equates/functions ; BASE EQU 0 ; 4200H for TRS80/Heath BDOS EQU BASE+05H ; Bdos location FCB EQU BASE+5CH ; File control block ; RDCON EQU 1 ; Console input CONOUT EQU 2 ; Console output DIRCON EQU 6 ; Direct console i/o RDCONS EQU 10 ; Read console buffer ; ; Ascii equates ; CTLC EQU 03H ; Control c BEL EQU 07H ; Bell BS EQU 08H ; Backspace TAB EQU 09H ; Tab CR EQU 0DH ; Carriage return LF EQU 0AH ; Linefeed DEL EQU 18H ; Del line char ^X SPC EQU 20H ; Space ; ; Set the following to match BYE and your system ; REMDRV EQU 2 ; Remote max drives REMUSR EQU 10 ; Remote max users SYSDRV EQU 2 ; System max drives SYSUSR EQU 15 ; System max users ; WHEEL EQU 3EH ; Location wheel byte MXDRIV EQU 3DH ; Location max drives MXUSER EQU 3FH ; Location max users ; ; System dependent options ; CLRSCR EQU 'Z'-40H ; Clear screen char ^Z MHZ EQU 4 ; System clock, Mhz WTIME EQU 23 ; Time for WAIT (100 = 10 secs) ; ; LOOPT EQU 'A' ; Low command option HIOPT EQU 'L' ; High command option ; ; Z80 code is utilized. If your CPU is not a Z80 you will have ; to convert to appropriate code via macros or direct code else ; include a macro library. ; ;-------------------------------------------------------------- ; ORG BASE+100H ; BEGIN: LD HL,0 ADD HL,SP ; Get old stack pointer LD (STACK),HL ; Save it LD SP,STACK ; Set new stack pointer ; XOR A ; Zero LD (BYFLAG),A ; To show BYE not running ; LD C,32 ; This combination determines LD E,241 ; If bye is there. CALL BDOS CP 77 ; Is it there? JP NZ,NOBYE ; No, skip over the next ; LD A,0FFH ; Yes, it is LD (BYFLAG),A ; So, set the flag CALL PASGET ; And get access password JP NZ,EXIT ; If password bad then exit CALL PCRLF ; Else print cr/lf ; NOBYE: LD A,(FCB+1) ; Command given at start? CP ' ' ; Test for none JP NZ,MENU1B ; If not blank see if valid ; ; First menu ; MENU1: LD HL,VSMSG ; Version msg CALL PRNTL LD HL,M1MSG ; Menu1 msg CALL PRNTL CALL RDCHAR ; Get char MENU1B: CALL UPCASE ; Be sure upper case CP 'B' JP Z,MENU1C ; To menu2 CP 'I' CALL Z,DOIO1 ; View or change i/o byte CP 'R' CALL Z,DODEF ; No wheel, max drv/usr for remote use CP 'S' CALL Z,DOMAX ; Set maxdrive/user = system max CP 'W' CALL Z,DOWHL ; Set wheel byte CP 'X' JP Z,EXIT ; Exit program JP MENU1 ; MENU1C: LD A,(BYFLAG) ; Get BYE flag CP 0FFH ; Was it there JP Z,MENU2 ; Yes, skip over LD HL,NOBYEM ; BYE not active msg CALL PRNTL CALL WAIT ; Slight delay JP MENU1 ; And go back to menu1 ; ; ; Set drives/users for remote usage ; DODEF: LD A,REMDRV-1 ; Remote maximums LD (MXDRIV),A ; For drive LD A,REMUSR LD (MXUSER),A ; And for user XOR A LD (WHEEL),A ; Clear wheel byte RET ; ; Set drives/users for special or non-remote use ; DOMAX: LD A,SYSDRV-1 ; System maximums LD (MXDRIV),A ; For drive LD A,SYSUSR LD (MXUSER),A ; And for user RET ; ; Set the wheel byte ; DOWHL: LD A,0FFH ; Set wheel byte LD (WHEEL),A RET ; ; View or change the i/o byte (CP/M 1.x or 2.x only) ; DOIO1: LD C,12 ; Return vers number CALL BDOS LD A,H CP 0 ; H=00 if CP/M JP NZ,DOIO2 ; Bad if not LD A,L CP 30 ; Check if < vers 3.x JP C,DOIO3 ; Skip over if okay ; DOIO2: LD HL,IONOMS ; Bad system msg (not 1.x, 2.x) CALL PRNTL JP WAIT ; Delay, then menu ; DOIO3: LD HL,GVMSG ; Value is... msg CALL PRNTL LD C,7 ; Get iobyte function CALL BDOS CALL OUTHX1 ; Display the value CALL PCRLF ; Cr/lf ; LD HL,SVMSG1 ; Set value msg CALL PRNTL CALL HEXGET ; Get hex input CP 0 ; If zero length JP Z,CABORT ; Then abort (no change msg) CALL VALBIN ; Convert to binary LD E,A ; Binary value now to E LD C,8 ; Set iobyte function CALL BDOS LD HL,SETMS1 ; Successful msg CALL PRNTL JP WAIT ; Delay, then menu ; ; Second menu ; MENU2: XOR A ; Put zero into LD (FUNCN),A ; Function number buffer LD HL,VSMSG ; Version msg CALL PRNTL LD HL,M2MSG ; Menu2 msg CALL PRNTL CALL RDCHAR ; Get char CALL UPCASE ; Be sure upper case CP 'P' ; Is it a "P" JP Z,MENU1 ; Go to first menu CP 'X' ; Is it a "X" JP Z,EXIT ; If yes, quit ; CP LOOPT ; Less than low option JP C,MENU2 ; Yes, try again CP HIOPT+1 ; Higher than high option CALL C,FUNCN0 ; No, continue on JP MENU2 ; Go to top of this menu ; ; FUNCN0: CALL PCHAR ; Display the char SUB 40H ; Make option binary ; ; Convert option to function number and save it for more use. ; Functions are 69-78 for options A-J and 81-82 for K-L ; FUNCN1: CP 'K'-40H ; If option less than this JP C,FUNCN2 ; Then add only 68 ADD A,2 ; Else add 2 more FUNCN2: ADD A,68 LD (FUNCN),A ; Store function ; ; Read and display the current value ; GETVAL: CP 82 ; Func 82 is "SET ONLY" JP Z,SETVL2 ; So skip reading LD HL,GVMSG ; Value is... msg CALL PRNTL LD C,A ; Function to C LD E,0FFH ; Get value CALL BDOS CALL OUTHX1 ; Display the value ; ; Set new value ; SETVL1: CALL PCRLF ; Cr/lf LD HL,SVMSG1 ; Set value msg CALL PRNTL CALL HEXGET ; Get hex input CP 0 ; If zero length JP Z,CABORT ; Then abort CALL VALBIN ; Convert to binary CALL VALCHK ; Check if valid entry CP 0FFH ; Was it bad JP Z,CABORT ; Yes, abort LD E,A ; Binary value now to E JP CHANGE ; Change to new value ; ; Set login hour and minute ; SETVL2: CALL PCRLF ; Cr/lf LD HL,SVMSG2 ; Login hour msg CALL PRNTL CALL HEXGET ; Get hex input CP 0 ; If zero length JP Z,CABORT ; Then abort CALL VALBIN ; Convert to binary CP 24 ; Greater than 23 JP NC,CABORT ; Yes, abort setting LD (BHOUR),A ; Else, save binary hour LD HL,SVMSG3 ; Login minute msg CALL PRNTL CALL HEXGET ; Get hex input CP 0 ; If zero length JP Z,CABORT ; Then abort CALL VALBIN ; Convert to binary CP 60 ; Greater than 59 JP NC,CABORT ; Yes, abort setting LD E,A ; Else, binary minute to E LD A,(BHOUR) ; Get binary hour LD D,A ; Put in D, fall into next ; ; Change value. Entry E = new binary value. ; CHANGE: LD A,(FUNCN) ; Function LD C,A ; Move to C CALL BDOS LD HL,SETMS1 ; Successful msg CALL PRNTL JP WAIT ; Delay, then menu ; ; Set aborted due to CR only or wrong value being entered. ; CABORT: LD HL,SETMS2 ; Abort (no change) msg CALL PRNTL ; ; Delay after messages. ; WAIT: LD HL,WTIME ; Time to wait (100 = 10 secs) WAITLP: CALL DELAY ; Delay .1 second DEC HL ; HL=HL-1 LD A,H OR L ; Is count zero JP NZ,WAITLP ; No, loop RET ; ; Exit from program ; EXIT: CALL PCRLF ; Cr/lf LD HL,(STACK) ; Get old cp/m (or mp/m) stack LD SP,HL ; Restore old stack pointer RET ; Return to ccp ; ;-------------------------------------------------------------- ; ; SUBROUTINES ; ; Convert binary value to ascii and display it ; OUTHX1: PUSH BC LD C,A ; Save RRA RRA RRA RRA CALL OUTHX2 ; High byte LD A,C CALL OUTHX2 ; Low byte LD A,C ; Restore POP BC RET ; OUTHX2: AND 0FH ; Output hex byte ADD A,90H ; Make ascii DAA ADC A,40H DAA CALL PCHAR ; Print it RET ; ;-------------------------------------------------------------- ; ; Print on console null terminated line pointed to by hl. ; PRNTL: LD A,(HL) ; Get char to a OR A ; Test for 0 end RET Z ; Return if 0 CALL PCHAR ; Else print it INC HL ; Point to next JP PRNTL ; Loop ; ;-------------------------------------------------------------- ; ; Print char in A reg. All regs preserved. ; PCHAR: EXX LD E,A ; Char to e EX AF,AF' LD C,CONOUT ; Console output CALL BDOS EX AF,AF' EXX RET ; ;-------------------------------------------------------------- ; ; Print carriage return and linefeed. All regs preserved. ; PCRLF: PUSH AF LD A,CR CALL PCHAR LD A,LF CALL PCHAR POP AF RET ; ;-------------------------------------------------------------- ; ; Get char from console ; RDCHAR: EXX RDLOOP: LD C,DIRCON ; Direct console i/o LD E,0FFH ; Indicate input CALL BDOS OR A ; Loop if no char (if a=0) JP Z,RDLOOP EXX RET ; ;-------------------------------------------------------------- ; ; Capitalize ascii character in A ; UPCASE: AND 7FH ; Mask out msb CP 61H ; < small a? RET C CP 7AH+1 ; Between small a and small z? RET NC AND 5FH ; Remove bit 5 (0x0x xxxx) RET ; ;-------------------------------------------------------------- ; ; Get two ascii hex chars or none. ; Exit A = number of chars. BUFFER = Ascii High and Low char. ; HEXGET: LD HL,BUFFER ; Storage buffer LD C,2 ; Maximum two chars LD B,0 ; Initialize counter HEXGT1: CALL RDCHAR CP CR ; If a cr JP Z,HEXEXT ; Then print new line CP BS JP NZ,HEXGT2 ; Branch if not bs CALL HEXBAK ; If bs, delete 1 char JP HEXGT1 ; Then loop ; HEXGT2: CP DEL JP NZ,HEXGT3 ; Branch if not del ; HEXDEL: CALL HEXBAK ; Delete a char JP NZ,HEXDEL ; Continue until buffer empty JP HEXGT1 ; Backs up over each char ; HEXGT3: CALL TSTHEX ; Test for hex characters JP NZ,HEXGT1 ; If not ok, try again LD E,A ; Save char LD A,B ; Is buffer full CP C ; Compare count and buffer len JP C,HEXSTO ; Jump if buffer no full LD A,BEL ; Full, ring console bell CALL PCHAR JP HEXGT1 ; Continue with read loop ; HEXSTO: LD A,E ; Get char back LD (HL),A ; Store in buff INC HL ; Incr buff ptr INC B ; Incr char count CALL PCHAR ; Print it JP HEXGT1 ; Continue with read ; HEXEXT: LD A,B ; Get char count CP 1 ; If one char JP Z,HEXGT1 ; Try for second or none CALL PCRLF ; Cr/lf LD A,B ; And ret with count in a RET ; HEXBAK: LD A,B ; Test number of chars OR A RET Z ; Exit if buffer empty DEC HL ; Decr buff ptr LD HL,BSSTRG CALL PRNTL DEC B ; One less char in buff RET ; ;-------------------------------------------------------------- ; ; Test validity of ascii hex characters entered. ; ; TSTHEX returns Zero Flag Set if char in A is hex (0-9,A-F,a-f) ; TSTHEX returns NZ if not. Char in A is unaffected. ; TSTHEX: PUSH BC ; Save bc LD C,A ; Save char in c CALL TSTDIG ; Is it a digit? JP Z,TSTYES CALL UPCASE ; Capitalize CP 'A' ; Less than a? JP C,TSTNOT CP 'F'+1 ; Less than or equal to f? JP NC,TSTNOT JP TSTYES ; ; TSTDIG returns Zero Flag Set if char in A is numeric (0-9). ; TSTDIG returns NZ if not. Char in A is unaffected. ; TSTDIG: PUSH BC ; Save bc LD C,A ; Save char in c AND 7FH ; Mask out msb CP '0' ; Less than 0? JP C,TSTNOT CP '9'+1 ; Less than or equal to 9? JP NC,TSTNOT JP TSTYES ; TSTYES: XOR A ; Set flag LD A,C ; Get char POP BC ; Restore bc RET ; TSTNOT: LD A,0FFH ; Set flag OR A LD A,C ; Get char POP BC ; Restore bc RET ; ;-------------------------------------------------------------- ; ; Convert two ascii characters to one byte binary. ; VALBIN: LD HL,(BUFFER) ; Get buffer contents LD A,L ; Reverse bytes LD L,H LD H,A CALL HEX2BN ; Do conversion RET ; ; Entry H = Ascii high L = Ascii low. Exit A = Binary byte ; Hex character validity is not done in this routine. ; HEX2BN: LD A,L ; Get low char CALL A2HEX ; Convert it to hex LD B,A ; Save hex value in b LD A,H ; Get high char CALL A2HEX ; Convert it to hex RRCA ; Shift hex val to upper 4 bits RRCA RRCA RRCA OR B ; Or in low hex value RET ; Exit with binary in reg a ; A2HEX: SUB 30H ; Subtract ascii offset CP 10 RET C ; Return if decimal digit SUB 7 ; Else subtr offset for letters RET ; ;-------------------------------------------------------------- ; ; Check if the binary value is ok for the function being set. ; ; Entry A = binary value ; Exit A = 0FFH if bad, else value to set if ok ; VALCHK: LD C,A ; Save binary value LD A,(FUNCN) ; Function CP 81 ; If 81 JP Z,VALCH1 ; Do from/to check CP 73 ; Greater than 72 JP NC,VALCH2 ; Yes, do either check JP VALCH1 ; Else, check from/to ; ; Check from/to value ; VALCH1: CALL VALTBL ; Get addr for compare LD A,C ; Restore binary value CP (HL) ; Less than low value JP C,VALBAD ; Yes, show bad INC HL ; Point to high value LD E,(HL) ; Move to E INC E ; Add 1 to it CP E ; Higher than high value JP NC,VALBAD ; Yes, show bad RET ; ; Check for either value ; VALCH2: CALL VALTBL ; Get addr for compare LD A,C ; Restore binary value CP (HL) ; Equal to low value RET Z ; Yes, return INC HL ; Else point to high value CP (HL) ; Equal to high value RET Z ; If no, fall thru ; ; Set to show bad ; VALBAD: LD A,0FFH ; 0FFH as our flag for bad RET ; ; Get addr of comparison value into HL ; VALTBL: LD A,(FUNCN) ; Function SUB 69 ; Less low so 0 = 69, etc ADD A,A ; A = 2*A LD E,A ; Doubled value to E LD D,0 ; DE = table offset LD HL,VALUES ; Addr of table ADD HL,DE ; Add offset to it RET ; ;-------------------------------------------------------------- ; ; 1/10 second delay routine ; DELAY: PUSH BC LD BC,4167*MHZ ; Timing constant * clock Mhz DELAY1: DEC BC LD A,B OR C JP NZ,DELAY1 POP BC RET ; ;-------------------------------------------------------------- ; ; Prompt for and get password. Password isn't echoed to console ; PASGET: LD D,2 ; Max two tries PASGT1: LD HL,PASMSG ; Prompt msg CALL PRNTL LD HL,PASWRD ; Point to password LD E,0 ; Show no errors PASGT2: PUSH DE ; Save de CALL RDCHAR ; Get char POP DE ; Restore de CALL UPCASE ; Make upper case CP 'U'-40H ; If ^U JP Z,PASGT1 ; Try again CP (HL) ; Check for match JP Z,PASGT4 ; Yes LD E,1 ; No, show miss CP CR ; Is it CR JP NZ,PASGT2 ; No, wait for CR PASGT3: DEC D ; More tries? JP NZ,PASGT1 ; Yes LD A,E ; Else get flag OR A ; Show if error existed RET ; Return not zero if error PASGT4: INC HL ; Point to next char CP CR ; Is it CR JP NZ,PASGT2 ; No, loop LD A,E ; Yes, get flag OR A ; Was there an error JP NZ,PASGT3 ; Not right RET ; Return zero set if ok ; ;-------------------------------------------------------------- ; ; Table of values for setting. Set login doesn't use this table ; Consult the documentation for BYE5xx before changing these. ; ; Either value, or between, is accepted for the following. ; VALUES: DEFB 0,4 ; Max drive (0=A, 1=B, etc) 69 DEFB 0,15 ; Max user (0=0, 1=1, etc) 70 DEFB 1,254 ; Timeout minutes 71 DEFB 0,9 ; Number of nulls (0-9 only) 72 ; ; Either value is accepted for the following. ; DEFB 0,32 ; Case switch (0=both cases) 73 DEFB 0,1 ; Line feeds (0=ok to send) 74 DEFB 0,1 ; WRTLOC flag (0=ok to hangup) 75 DEFB 0,1 ; Hardlog flag (0=disable prtr) 76 DEFB 0,1 ; Modem i/o (0=modem on) 77 DEFB 0,1 ; Bell flag (1=bell on) 78 DEFS 2 ; RTCBUF get only unused here 79 DEFS 2 ; LCDATA get only unused here 80 ; ; Either value, or between, is accepted for the following. ; DEFB 0,254 ; Max time allowed on system 81 ; ;-------------------------------------------------------------- ; ; Messages/buffers ; M1MSG: DEFB CR,LF,TAB,TAB,TAB DEFB 'Set or change Page 0 values',CR,LF,LF,TAB DEFB 'B> BYE menu I> i/o byte S> system values' DEFB CR,LF,TAB DEFB 'R> remote values W> wheel set X> exit to CPM' DEFB CR,LF,LF,TAB DEFB 'Option desired: ',BS,0 ; M2MSG: DEFB CR,LF,TAB,TAB,TAB DEFB 'View or change BYE values',CR,LF,LF,TAB DEFB 'A> max drive B> max user C> timeout value' DEFB CR,LF,TAB DEFB 'D> nulls E> upr/lwr case F> linefeed' DEFB CR,LF,TAB DEFB 'G> wrtloc flag H> hardon flag I> mdmoff flag' DEFB CR,LF,TAB DEFB 'J> console bell K> max time on sys L> login time' DEFB CR,LF,TAB DEFB 'P> first menu X> exit to CP/M' DEFB CR,LF,LF,TAB DEFB 'Option desired: ',BS,0 ; GVMSG: DEFB CR,LF,LF,TAB DEFB 'Current value is: ',0 SVMSG1: DEFB CR,LF,TAB DEFB 'Set to hex value: ',0 SVMSG2: DEFB CR,LF,TAB DEFB 'Set hour to hex value: ',0 SVMSG3: DEFB CR,LF,TAB DEFB 'Set min. to hex value: ',0 ; SETMS1: DEFB CR,LF,TAB DEFB 'Successful',0 SETMS2: DEFB CR,LF,TAB DEFB 'Not Changed',BEL,0 ; NOBYEM: DEFB CR,LF,LF,TAB ; Bye not active msg DEFB 'BYE is not active',0 ; IONOMS: DEFB CR,LF,LF,TAB ; Bad system msg, for iobyte set DEFB 'Only for CP/M 1.x or 2.x',BEL,0 ; PASMSG: DEFB CR,LF ; Password msg DEFB 'Password: ',0 PASWST: DEFB '>' ; Start marker PASWRD: DEFB 'DDT' ; The password itself DEFB CR ; End of password, CR-only to erase it DEFB 0,0,0,0,0,0,0 ; Room for larger pswd (to 10 chars) PASWND: DEFB '<' ; End marker ; VSMSG: DEFB CLRSCR ; Version msg DEFB CR,LF,LF,TAB,TAB DEFB 'RPASS Version ' DEFB VERS/10+'0','.',VERS MOD 10 +'0' DEFB ' Remote System Utility',CR,LF,0 ; BSSTRG: DEFB BS,SPC,BS,0 ; BYFLAG: DEFB 0 ; Bye flag FUNCN: DEFB 0 ; Function number buffer BUFFER: DEFS 2 ; Ascii hex buffer BHOUR: DEFB 0 ; Binary hour ; DEFS 64 ; Room for 32 level stack STACK: DEFS 2 ; Old stack saved here ; END