IMD 1.15: 1/01/1998 1:05:30 fog hak 022         -FOG/HAK022/HAK#022CRC+/HAK#022DOC BYE3-OS ASM BYE3-OS ASM !BYE3-OS ASM"#OZFILE52ASMi$%&'()* First Osborne Group (FOG) -FOG/HAK.022 Copyrigh 198 b Firs Osborn Grou (FOG t th exten no copyrighte b th origina autho fo th exclusiv us an enjoymen o it members An reproductio o distributio fo profi o persona gai i strictl forbidden Fo information contac FOG P O Bo 3474 Dal City C 94015. These disks have the files necessary to use the Osborne 1 with the Osborne/CTS Comm-pac modem as a remote answering de  vice. The source files are provided for BYE3.18 and XMODEM74. Bye answers the phone and calls up the RBBS message system. Xmodem allows files to be transferred to and from the system while in CP/M. Because the setup of these files is quite different for each system (due to available user areas, disk sizes and numbers, etc) I haven't assembled them. They will all assemble with ASM, so you shouldn't have any problems! These are all known working versions just as is, so go ahead and try out your  ; BYE3 - REMOTE CONSOLE PROGRAM FOR CP/M AND MODEM ; MAIN: EQU 3 VERS: EQU 18 MONTH: EQU 02 DAY: EQU 01 YEAR: EQU 84 ; ; This program allows modem callers to use a CP/M system just as if they ; were seated at the system console. Special assown options! OZFILE will let you search the entire system for any files you specify on the command line. It looks for the maxdrive and maxuser bytes to provide system security. Thanks to Roy Robinson for this version.embly-time options al- ; low limiting the caller's access by password and/or access to only a ; message-service program. This is based on a program written by Dave ; Jaffe in January, 1979. A number of external routines are available ; to adapt this program to various computers. It may be assembled with ; either ASM.COM or MAC.COM. ; ; BYE3 is placed in the public domain. It may be updated or altered but ; should again be placed in the public domain. Send a copy of any new ; changes to TCBBS in Detroit: (313) 846-6127 ; ;======================================================================= ; ; (Put only the current update comments here, move the previous one down ; with the others. Will assist those who want to see "what is new".) ;   ; 02/02/84 If the TIMEOUT option is set YES, the program aborts after 5 ; v3-18 minutes of no user activity. This was not working properly. ; Now it does (tested on two systems). Idea for the fix ob- ; tained from Adam Koczarski. Added ruse. ; ; NOTE: EARLIER VERSIONS OF BYE REQUIRED A LOT OF EXTRA WORK TO USE THE ; BYELOW OPTION. THIS VERSION REQUIRES NO ADDITIONAL WORK OR IN- ; FORMATION TO BE SUPPLIED. IT WILL LIKELY REPLACE ALL VERSIONS ; USED IN HIGH RAM (ABOVE BIOS) SINCE NO Eoutine to easily change ; version and update information. (Adapted from one developed ; by Frank Gaude'.) Shortened previous history to those items ; still of current interest. - Irv Hoff ; ;===========================================XTRA WORK IS REQUIRED. ; ;======================================================================= ; ; BYE3 supports the following modems and/or USART combinations: ; ; SMDM routine - by Steve Holtzclaw B3SM51-3.ASM (includes 8251 I/O) ; 1602 (TRS-8============================ ; ; If the option BYELOW is set 'NO' it automatically locates itself above ; the BIOS at top of memory. Otherwise it sits just below CCP, not re- ; quiring any alteration in the location of CP/M via MOVECPM. ; ; BYE3 Not0) - by Paul Traina B3TRS-3.ASM ; 2651 - by Paul Traina B3COMP-3.ASM ; 8250 - by Paul Traina B3HZ89-3.ASM ; 8251+CTC timer - by Irv Hoff B3DATA-3.ASM ; APPLE-CAT - by Dave Roznar B3ACAT-3.ASM ; HZ-100 - by John Ferguson B3HZ10-3.ASM ; Kayproes: This update of BYE contains a special loader routine ; which will compute the proper offset with which to relocate BYE. The ; loader routine is based on a routine used in the Consolx (tm) program ; sold by Hawkeye Grafix. This loader, greatly mod - by Steve Sanders B3KPRO-3.ASM ; MM100 - by Dave Jaffe B3DCH-3.ASM ; MMII (Apple) - by Paul Traina B3MMII-3.ASM ; PMMI - by Ward Christensen B3PMMI-3.ASM ; SIO - by Steve Fox B3SIO-3.ASM ; Televideo 802 - by K. Robesky B3T802-3.ASM ; ; ified and enhanced, ; will load BYE3 below the CCP or above the BIOS as desired. All you ; need to do is: (1) choose the desired options, (2) patch in the file ; for your computer/modem in the +++ area, (3) finish editing then as- ; semble, load and ; Most users of this program will have an auto-answer modem such as the ; Hayes 300 or 1200, the U.S.Robotics or Rixon. A routine that supports ; these modems has been included. Set the SMODEM equate to 'YES' if you ; have one of these modems, no if a  nother type of auto-answer modem such ; as the PMMI, Bell 212A, etc. (This routine may easily be found if you ; type $$$ for easy location. It may be replaced with other automatic ; modem routine if you have one you like better but has given excellent ame (BYE). ; ;======================================================================= ; ; 01/01/83 Added COVECT routine so XMODEM can automatically find the ; v3-17 correct CONOUT address if BYE3 is being used. (You set the ; USECON equate to  ; results to date, with no problems reported.) ; ; NOTE: The correct routine would be inserted very near the end, in the ; area marked "+++ INSTALL YOUR MODEM ROUTINES HERE +++". Then ; edit the options, reassemble, load and it will be ready to usYES in XMODEM, saving any calculations that ; limit XMODEM to one particular BIOS location. This is in ; keeping with the fully automatic features offered by BYE3.) ; Modified the Smartmodem routine with the help of Rick Bates. ; (If usinge. ; ;======================================================================= ; ; The program does the following: ; ; 1) Hangs up the phone ; 2) Awaits ring detect, allows exit to CP/M if local KBD ; types CTL-C ; 3) Outputs carrier (see callb the Hayes Smartmodem 300 or 100, you might want to ; replace the simple routine with one of the more complex ones ; written by Steve Holtzclaw or Don Brown. Other brands do not ; not appear to have a similar problem.) ; - Irv Hoff ; ; ack routines) ; 4) Awaits incoming carrier going to step 1. If none found ; in 15 seconds, hangs up ; 5) Asks number of nulls (0-9) ; 6) Types the file "WELCOME" from disk, (oprional) llowing ; CTL-C to skip it ; 7) Asks for a password (opti11/27/83 Added USEZCPR routine (similar to one developed by Wayne Mas- ; v1.2 ters in another program). It automatically sets the maximum ; drive and user from ZCPR if USEZCPR is 'YES'. Also added his ; SMAXDRV and SMAXUSR to restore normal onal), allowing 3 tries to get ; it right. ; 8) When password entered, (optional), drops into CP/M. ; 9) Caller can leave by hanging up, (any time carrier is ; lost, it waits then goes back to step 1) or the ; caller may type the program nvalues for the SYSOP ; when the program is aborted with ^C. Corrected 36 bytes which ; had all 7th bits set high. Added colons to all labels. Some ; minor changes. Ran through NEATL, FILTEX11 and TABASM. Re- ; named and reworked all the   BYE2 external overlays so they can ; be used with BYE3. - Irv Hoff ; ; 11/07/83 Fixed numerous bugs including the following: ; v1.1 1) When running BYEHI the BDOS jump vector was re-routed al- ; lowing programs to overwrite the CCP, BDturn LF: EQU 0AH ;ASCII line feed ; IOBYTE: EQU 0003H ;location of CP/M iobyte FCB: EQU 005CH FCBRNO: EQU FCB+32 ; ; ; BDOS equates ; BDOS: EQU 0005H CI: EQU 1 WRCON: EQU 2 DRECTIO: EQU 6 PRINTF: EQU 9 CSTS: EQU 11 OPEN: EQU 15 ROS, and BIOS. ; 2) When running BYELOW the program always looked at the BDOS ; jump vector for its load point. When BYE3 was running ; and a caller typed BYE it would load 2k below the first ; copy. I fixed this by testing for EAD: EQU 20 STDMA: EQU 26 ; ; ; You will likely also want to change the password, located below at ; label 'PASSWD', and the messages printed at label 'WELCOME' and just ; above label 'HANGUP'. The names of the welcome and .com files are at ; labcarrier before relo- ; cating and if there was a carrier I did not relocate but ; just jumped to the BYE start. ; 3) When program was being relocated the uninitialized data ; area were also being copied up to high ram causing thels 'WELFIN' and 'COMFCB' respectively. ; ; ;*********************************************************************** ; ; OPTION CONFIGURATION SECTION ; ;*********************************************************************** ; ; ;----------e ; saved BIOS jump table and the counters to be overwritten. ; 4) Fixed relocation for the remote function keys. ; - David Schmidt ; ; 08/10/83 New loader added producing BYE3 vers 1.0. ; v1.0 - Alfonso Guerra ; ; 06/23/83 Origin---------------- general options ---------------------------- ; BYELOW: EQU YES ;yes, running BYE3 below CCP; no for above BIOS RAMTOP: EQU 0FFFFH ;last available RAM if BYELOW is 'NO' SMODEM: EQU NO ;yes, for Smartmodem, no for other types ; IOVal version of BYE2+ (Based on ByeII v1.4-A) ; - Fred Skinner ; ;======================================================================= ; ; System equates ; YES: EQU 0FFH ;for conditional assembly NO: EQU 0 ; CR: EQU 0DH ;ASCII carriage reAL: EQU 0 ;initial value for IOBYTE (only if MINICK 'YES') MINICK: EQU NO ;yes, running MINICBBS OXGATE: EQU yes ;yes, running OXGATE RCPM-BBS system RBBSCK: EQU NO ;yes, running RBBS - sets/resets 'WRTLOC' flag ; ; ;----------------------------  ------------------------------------------- ; OSBORNE: EQU YES ;YES this is an Osborne 1 ; ALLDEV: EQU NO ;yes, retain PUN: RDR: and LST: devices BOOTMSG: EQU NO ;yes, print "please wait..." message CALLBAK: EQU no ;yes, allow callback feature n off remote send BLNKKEY: EQU 'B'-40H ;keycode to "blank out" remote terminal CCSDISK: EQU NO ;yes, CCS disk controller CLOSS: EQU 5 ;if carrier dies, wait 5 secs. before hanging up COMUSR: EQU 00 ;user # of .COM file to be called after answer CPM2 COMFILE: EQU yes ;yes, chain a .COM file upon carrier reception ;.....next time BYE3 answers the phone. DECIMAL: EQU YES ;yes, decimal value for userlog DUAL$IO: EQU YES ;yes, console/modem linked together EXFILE: EQU NO ;yes, chain a .COM file up: EQU YES ;yes, using CP/M 2.2 CTRLC: EQU 'K'-40H ;map ^C to this if 0000H<>C3H (nb: ^O=15 decimal) CWAIT: EQU 20 ;wait up to 20 seconds for carrier at first EXUSR: EQU 00 ;user # of .COM file to be called upon exit IMSAI: EQU NO ;yes, if using IMon loss of carrier FKEYS: EQU yes ;yes, local console has special function keys HARDLOG: EQU NO ;yes, echo remote input to printer LGONMSG: EQU NO ;yes, print message before "how many nulls" msg PRINTER: EQU NO ;yes, retain list device PRNTGB: EQU YSAI computer with front panel INULLS: EQU 01 ;initial number of nulls LOSER: EQU NO ;yes, warm boot overwrites part of the BIOS LXID: EQU 11H ;define byte of LIX D,nnnn to fake loader LXIH: EQU 21H ;define byte of LXI H,nnnn to fake loader MHZ: EES ;yes, print "Goodbye..." message PRNTWB: EQU NO ;yes, print a string each time system warm boots PWRQD: EQU NO ;yes, password needed to login RKEYS: EQU NO ;yes, remote console has special function keys TIMEOUT: EQU YES ;yes, auto logout for sleeQU 4 ;processor clock in MHz MSGKEY: EQU 'Q'-40H ;keycode to print "Message from SYSOP: " MSPEED: EQU 003CH ;baud rate pointer NORING: EQU NO ;yes, UART ring indicator NOT available NZCPR: EQU NO ;yes, if running NEWZCPR under secure mode SELPASpy callers TOVALUE: EQU 5 ;minutes to auto logout USRLOG: EQU yes ;yes, count number of users WBRTN: EQU NO ;yes, do function each time system warm boots ; ; ;---------- system and hardware dependent options -------------- ; BLKOUT: EQU YES ;turS: EQU NO ;require a password SENSE: EQU 0FFH ;sense switch port number SMAXDRV: EQU 16 ;number of drives available to SYSOP SMAXUSR: EQU 16 ;number of user areas available to SYSOP SYSDKEY: EQU 'O'-40H ;keycode to print "System going down in 5 min.."   TWITKEY: EQU 'N'-40H ;keycode to hangup modem manually WELFILE: EQU YES ;yes, to send a WELCOME file WELUSR: EQU 00 ;user # of WELCOME file WHEEL: EQU 003EH ;location of NZCPR's wheel flag ZILOG: EQU YES ;yes, using a Z-80 or Z-800 ; ; ; If USEs to switches: ; IF IMSAI BLACKSW: EQU 04H ;turn on to black out remote end ENABLF: EQU 08H ;turn on to enable special function keys LOGSW: EQU 01H ;turn on for hardcopy PWDSW: EQU 02H ;turn on for 'password' mode ENDIF ;IMSAI ; ; ; TheZCPR is YES, it automatically sets MAXDRIV and USERMAX from the ; ZCPR locations. Otherwise it uses the vaules you insert for MAXDRV ; and MAXUSR. ; USEZCPR: EQU NO ;yes, if using ZCPR to set max drive and user # MAXDRIV: EQU 003DH ;ZCPR lolcation ore are some cases where warm boot overwrites the initial bios jump ; table. This problem was solved for the Superbrain 3.0 bios by find- ; ing a warmboot call to HIGH in the BIOS. This call is then patched by ; BYE. The form of the call is: WBCALLf MAXDRIV byte MAXUSER: EQU 003FH ;ZCPR location of MAXUSR byte MAXDRV: EQU 2 ;highest drive supported (2=B:) MAXUSR: EQU 7 ;highest user area (set to 0 for CP.M 1.4) ; ;----------------------------------------------------------------------- ; BP1 CALL WMSTRT ; IF LOSER WBCALL: EQU 0DE48H ;check this in your BIOS ; ; ; The following location is called ; WMSTRT: EQU EE48H ;check this in your BIOS ENDIF ;LOSER ; ; ;***************************************************************10: EQU 0 ;110 bps - baud rate pointers for MSPEED BP300: EQU 1 ;300 bps BP450: EQU 2 ;450 bps BP600: EQU 3 ;600 bps BP710: EQU 4 ;710 bps BP1200: EQU 5 ;1200 bps BP9600: EQU 8 ;9600 bps BP19200: EQU 9 ;19200 bps ; ;------------------------******** ; ; END OF OPTION CONFIGURATION SECTION FOR BYE3 ; ;*********************************************************************** ; ; ORG 100H ; ; ;----------------------- Special Loader Routine ------------------------ ; ; START: L----------------------------------------------- ; IF CCSDISK DISK: EQU 034H ;disk control port DISKON: EQU 071H ;motors on, select disk A: DISKOFF: EQU 051H ;motors off, select disk A: ENDIF ;CCSDISK ; ; ; Assignment of front-panel optionXI SP,ISTACK ;set stack for initialization routine ; IF BYELOW ; IF NOT OSBORNE CALL MDCARCK ;check to see if BYE3 is already loaded ENDIF ;NOT OSBORNE ; IF OSBORNE ;relocate GETSTAT and MDINP LXI H,GETSTAT ;above 4000H LXI D,400  0H LXI B,MDOUTP-GETSTAT DB 0EDH,0B0H ;Z80 LDIR CALL 4000H PUSH PSW ANI DCD CNZ 4000H+MDINP-GETSTAT POP PSW CMA ANI DCD ENDIF ;OSBORNE ; LHLD BDOS+1 ;load BDOS vector JZ STARTA ;no carrier, go relocate code INX H ;com ENDIF ;ZILOG ; UPDATE: XCHG ;move the source addrress into 'HL' CALL NEGHL ;prepare value for subtraction DAD D ;form the program offset SHLD OFFSET ;save the program offset XCHG ;set up the offset register LXI H,ENDOBJ ;get the endipute start of BYE3 INX H INX H PCHL ;go execute already loaded code ; STARTA: LXI D,-(2048+256) ;2k btyes in CCP plus 1 sector DAD D ;make room for the CCP ENDIF ;BYELOW ; IF NOT BYELOW LXI H,RAMTOP-(OBJEND-PEND) ENDIF ;NOT BYELng addr of the prgm code DAD D ;form new ending addr (new location) SHLD ENDRNG ;save the ending addr of the prgm code LXI H,BEGOBJ ;get the start addr of the program code DAD D ;form new beginning addr (new location) ; ; ; The following codOW ; ; ; HL now contains the destination address of BYE3 ; LXI D,PEND-1 ;set up the source pointer LXI B,PEND-BEGOBJ ;set up byte counter ; ; ; This is the long version for 8080s and 8085s ; IF NOT ZILOG BLOCK: LDAX D ;get program byte Me determines whether or not an address is within the ; BYE prgm and sets it to the new address if it is - otherwise it will ; not disturb the code... ; DCX H ;set up the sourc pointer for the modi- ;..fication routine entry MODIFY: INX H ;poinOV M,A ;move program byte MOV A,B ;get byte count ORA C ;finished block transfer? JZ UPDATE ;yes, check on the opcode values DCX D ;no, set source pointer DCX H ;set destination pointer DCX B ;set byte counter JMP BLOCK ;continue bloct to the next (hopefully) instr. DB LXID ;get the address of the end of BYE3 ; ENDRNG: DW 0 MOV A,E SUB L MOV A,D SBB H ;have we finished moving this block? JC BEGIN ;yes, we can begin now. ; ; ; Here is where we test for the 3-byte opck transfer until finished ENDIF ;NOT ZILOG ; ; ; The following is for the Zilog Z-80 or Z-800. ; IF ZILOG XCHG ;reverse source and destination for lddr DB 0EDH,0B8H ;these are the codes for lddr XCHG ;restore regs to original order odes ; MVI B,INST3E-INST3 ;get the number of elements in the table LXI D,INST3 ;set up the 3-byte opcodes table pointer ; THRBYT: LDAX D ;get opcode byte from table CMP M ;is this byte a 3-byte opcode? JZ CHANGE ;change the 2nd and 3rd bytes   if needed INX D ;no, advance table pointer DCR B ;end of 3-byte table? JNZ THRBYT ;no, keep looking ; ; ; Skip all the 2-byte opcodes - this keeps the transfer program from ; trying to figure out what the second byte is. ; MVI B,INST2E-INS ; DCX H ;set back pointer to the LSB of the addr DB LXID ;load DE with the offset value ; OFFSET: DW 0 MOV A,M ;get base address ADD E ;change LSB to new address MOV M,A ;update memory INX H ;advance pointer to the MSB of the addr MOT2 ;get the number of elements in the table LXI D,INST2 ;set up the 2-byte-opcodes-table pointer ; TWOBYT: LDAX D ;get opcode byte from table CMP M ;is this byte a 2-byte opcode? JZ SKIP ;yes, skip it and continue DCR B ;no, end of 2-byte taV A,M ;get the MSB of the base addr ADC D ;change LSB to new address MOV M,A ;update memory JMP MODIFY ;take care of the next instruction ; ; ; Small subroutine to negate the contents of HL ; NEGHL: MOV A,H CMA MOV H,A ;get the complemeble? INX D ;advance table pointer JNZ TWOBYT ;no, keep looking JMP MODIFY ;yes, it's a one-byte opcode, keep going ; SKIP: INX H ;advance object code pointera JMP MODIFY ;continue search ; CHANGE: LXI D,OBJEND ;set up end of range pointer nt of the MSB MOV A,L CMA MOV L,A ;get the complement of the LSBb INX H ;make 'HL' totally negative RET ; ; ; Prepare to branch to the bye program ; BEGIN: EQU $ ; IF BYELOW LHLD BDOS+1 PUSH H LXI D,BEGOBJ LHLD OFFSET ;get prg LXI B,BEGOBJ ;set up beginning of range pointer ; ; ; See if the address is above the range ; INX H ;advance pointer to the LSB of the addr MOV A,E SUB M INX H ;advance pointer to the MSB of the addr MOV A,D SBB M JC MODIFY ; ; ; Sram offset DAD D ;form address of new BDOS address SHLD BDOS+1 ;update BDOS vector INX H POP D MOV M,E INX H MOV M,D INX H ENDIF ;BYELOW ; IF NOT BYELOW LXI D,BEGOBJ2 ;start of BYE3 code LHLD OFFSET DAD D ;'HL' >start of ree if the address is below the range ; DCX H ;set back pointer to the LSB of the addr MOV A,M SUB C INX H ;advance pointer to the MSB of the addr MOV A,M SBB B JC MODIFY ; ; ; Update the value of this address by adding the offset to it elocated code ENDIF ;NOT BYELOW ; PCHL ;jump to relocated BYE3 program ; ; ; The following table defines the 3-byte load instructions used in the ; 8080 instruction set. ; INST3: DB 01H DB 11H DB 21H DB 22H DB 2AH DB 31H DB 32H    DB 3AH DB 0C2H DB 0C3H DB 0C4H DB 0CAH DB 0CCH DB 0CDH DB 0D2H DB 0D4H DB 0DAH DB 0DCH DB 0E2H DB 0E4H DB 0EAH DB 0ECH DB 0F2H DB 0F4H DB 0FAH DB 0FCH ; INST3E: EQU $ ;end of 3 byte op codes ; ; The following tab*********************************************************** ; ; Here is a quickie handy reference table to use so we do not get mixed ; up. Please it in any future changes. ; ; |mxusr|mxdrv|toval|nulls|ulcsw|lfeeds|wrtloc|hardon|lostflg|covect| ; |1le is the listing of the 2-byte opcodes used in the ; 8080 instruction code set. ; INST2: DB 06H DB 0EH DB 16H DB 1EH DB 26H DB 2EH DB 36H DB 3EH DB 0C6H DB 0CEH DB 0D3H DB 0D6H DB 0DBH DB 0DEH DB 0E6H DB 0EEH DB 0F6H D byt|1 byt|1 byt|1 byt|1 byt|1 byte|1 byte|1 byte|1 byte |2 byes| ; ;*********************************************************************** ; ; Runtime maximum user area (unused under CP/M 1.4) ; MXUSR: DB MAXUSR ; ; ; Runtime maximum drive avaiB 0FEH ; INST2E: EQU $ ;end of 2 byte op codes ; ; ; Set aside space for the stack region ; DS 20H ; ISTACK: DW 0 ;top of stack ; ; ;----------------------------------------------------------------------- ; ; THE FOLLOWING CODE GETSlable ; MXDRV: DB MAXDRV ; ; ; Number of minutes to wait before timeout ; TOVAL: DB TOVALUE ; ; ; Number of nulls to put after a carriage return ; NULLS: DB INULLS ; ; ; Upper-case only switch, 32 for uppercase, 0 for upper/lowercase ; ULC MOVED ; TO HIGH RAM BY THE LOADER ; PROGRAM, WHERE IT IS EXECUTED. ; ;----------------------------------------------------------------------- ; BEGOBJ: JMP 0 ;filled by begin if BYELOW BEGOBJ2:JMP START0 ;hop over fixed vectors ; SW: DB 0 ; ; ; Line-feed masking bit (non-zero= mask line feeds) ; LFEEDS: DB NO ; ; ; Location RBBS pokes so modem does not hang-up during disk writes ; WRTLOC: DB NO ; ; Switch to let SYSOP turn on/off the hard log (so his work remotely ; wiMCBOOT: JMP MBOOT ;off to warm boot JMP PRNLOG ;go print out items of interest ; ; Variables follow in a predefined order that can be manipulated by a ; passworded or other program to give special users different capabili- ; ties. ; ;************ll not show up on the hardlog and waste all that paper) if HARDLOG ; is set 'NO', this is ignored, but takes up space so that smart pro- ; grams will not screw stuff up when they change these locations. ; ; HARDON: DB YES ; ; ; LOSTFLAG has been mo  ved up here, so that we can make BYE hang-up the ; the phone without the "good-bye" message (like if we kill a twit). ; LOSTFLG:DB NO ; ; ; Console output vector which points to the "local console" output rou- ; tine. This address is used by externn to disconnect during a file update. MINICBBS sets the ; high-order bit of IOBYTE (address 0003H) to indicate a file update is ; in progress. ; IF MINICK MVI A,IOVAL ;get proper initial value STA IOBYTE ;set it in IOBYTE ENDIF ;MINICK ;al XMODEM programs to set their ; CONOUT address automatically if their USECON equate is set to YES. ; COVECT: DW CONOUT ;used by XMODEM programs to find CONOUT DB 'BYE' ;tells XMODEM that BYE3 is being used ; ; ;********************************* ; ; Do not allow a remote user to do 'BYE /A' ; CALL MDCARCK ;call modem carrier check routine JNZ GOODBY ;we have carrier, so say bye bye... ; ; ; Identify version of program ; MVI C,PRINTF ;print function LXI D,VMSG ;signon message C************************************** ; ; THIS IS THE OFFICIAL START OF THE BYE PROGRAM ; ;*********************************************************************** ; ; ; If the carrier is lost - hang up, await ring. Otherwise, say goodbye, ; ALL BDOS ; ; ; Check for /A option on command - request to go immediately into the ; answer mode ; LXI H,FCB+1 ;get first character MOV A,M CPI '/' ;option? JNZ HANGUP ; ; ; Got an option - validate it ; INX H ;get which option it is.and hang-up. ; START0: EQU $ ;start of the BYE program ; IF BYELOW LHLD BDOS+1 ;get beginning address of BYE3 program SHLD BDADDR ;save address of BYE3 start ENDIF ;BYELOW ; XRA A ;a=0 STA LOSTFLG ;show no carrier lost ; IF RKE.. MOV A,M STA OPTION ;save it, we might need it later CPI 'A' ;answer immediately? JZ ANSWER ;skip to answer routine ; IF COMFILE CPI 'C' ;answer and do comfile? JZ ANSWER ;skip to answer routine ENDIF ;COMFILE ; IF USRLOG ;YS STA BYTEB ;initialize remote key pointers LXI H,0 SHLD BYTEA ENDIF ;RKEYS ; ; ; Set MINICK to 'YES' if you use MINICBBS and want to take advantage of ; its feature which can prevent the modem from hanging up if the caller ; should happecheck for reset of counters CPI 'R' CZ RESET ENDIF ;USRLOG ; JMP HANGUP ;we know it is local, so skip call to ;..carrier check ; ; No option, or invalid one ; NOSLASH:CALL CARCK ;signed off with this program? JC HANGUP ;nobody the  re ; GOODBY: EQU $ ;Issue good-bye and undo Bios patches ; IF PRNTGB LXI H,GBMSG ;good-bye message CALL ILPRT ;print this message CALL DELAY ;let the good-bye message finish CALL DELAY ; before calling up BYE3 pgm again ENDIF ;PRNTIF NORING ;if modem can't check for ring CALL MDCARCK ;check for carrier JNZ ANSWER ;we have carrier, let's say hello. JMP RINGWT ;nope, loop ENDIF ;NORING ; IF NOT NORING RINGW2: CALL MDRING ;call ring-check routine JZ RINGWT ;not GB ; CALL UNPATCH ;undo BIOS patches ; ; ; Nobody there, or we are done, so hang up ; HANGUP: LXI SP,STACK ;set up local stack XRA A ;force next warmboot to user 0 STA 0004H ;and drive a: MVI C,14 MOV E,A CALL BDOS MVI A,' ' ;do notringing... ; ; ; The phone may be ringing. Wait .1 sec and look again to make sure it ; is not just relay bounce ; CALL DELAY ;.1 sec delay for debounce CALL MDRING ;modem ringing? JZ RINGWT ;no, must have been a relay bounce ; ; ; The ph allow options STA OPTION ; IF CPM2 AND COMFILE MVI C,32 ;set CP/M user area function MVI E,COMUSR ;location of our COMFILE CALL BDOS ENDIF ;CPM AND COMFILE ; IF COMFILE CALL LODCOM ;load the .COM file ENDIF ;COMFILE ; ; ; one is definitely ringing, now wait until ring is finished ; ENDRING:CALL DELAY ;.1 sec delay for debounce CALL MDRING JNZ ENDRING ;wait until ring is finished ENDIF ;NOT NORING ; ; ; This routine minimizes the computer from interfering witMake phone hangup ; HANGUP2:CALL MDINIT ;call modem initialization routine ;(will hang up the modem) IF CCSDISK CALL DSKOFF ;turn off drives ENDIF ;CCSDISK ; MVI A,0C3H ;clear any traps left from .COM file STA 0 ; ; ; Await ringh the normal ; house hold phone use by having computer users dial, let the phone ring ; once, hang up and then dial again. When the phone rings only once, it ; alerts the computer which then waits for and answers any ring which ; occurs within the nexing - check local keyboard for CTL-C exit request. Note: ; Must do input via BDOS because CBIOS patches are not done until the ; call comes in. ; RINGWT: CALL UCSTS ANI 7FH ;strip parity bit CPI 'C'-40H ;CTL-C? CZ USRCHK ;check for exit ; t 45 seconds. (This assumes you left the ringer ; connected so you will in fact hear it ringing continuously and know it ; is somebody expecting a voice-answer.) ; IF (NOT NORING) AND CALLBAK ;next routines set CALLBAK MVI L,45 ;delay 4.5 seconds   for next ring ; WAITNX: CALL DELAY ;wait .1 seconds DCR L ;more to go? JNZ WAITNX ;yes, loop CALL MDRING ;ringing? JZ EXPECT ;no?...it's for me! ; ; ; If second ring, then check for third ring, in case phone exchange the ; caller is usianswer it CALL DELAY ;wait .1 second DCX H ;HL=HL-1 MOV A,H ORA L ;is count zero? JNZ RELOOK ;no, look some more JMP HANGUP2 ;count done, wait for new call ENDIF ;(NOT NORING) AND CALLBACK ; ;------------------- end of callback routng is not synchronized with that of the computer. ; ENDRNG2:CALL MDRING JNZ ENDRNG2 ;wait until ring is finished MVI L,45 ;delay 4.5 seconds for next ring ; WAITNX2:CALL DELAY ;wait .1 seconds DCR L ;more to go? JNZ WAITNX2 ;yes, loop CAines -------------------------- ; ; Modem setup ; ANSWER: EQU $ ;setup the modem ; IF BYELOW CALL BDCHEK ENDIF ;BYELOW ; IF NZCPR ;only when using NEWZCPR w/secure mode XRA A ;when running NZCPR for your CCP. STA WHEEL ;answer thLL MDRING JZ EXPECT ;no?...then is is for me! ; ; ; Call is not for the computer - wait until ringing is done, then reset. ; WAITNR: MVI L,100 ;wait for 10 seconds of silence ; WAITNRL:CALL DELAY ;delay .1 seconds CALL MDRING JNZ WAITNR ;ye phone in non-wheel mode ENDIF ;NZCPR ; IF USRLOG AND PWRQD;count # of logon attempts LXI H,OLDUSR ;get # of attempts CALL BOPLOG ;call routine to add one ENDIF ;USRLOG AND PWRQD ; ANSWERA:CALL MDANSW ;answer phone at 300 bps MVI Aes, wait 10 more seconds DCR L ;no ring, maybe we're done JNZ WAITNRL ;no, loop some more ENDIF ;(NOT NORING) AND CALLBAK ; IF (NOT NORING) AND CALLBAK AND USRLOG LXI H,NONUSR ;record as a voice call CALL BOPLOG ;call routine to add one,BP300 ;poke in MSPEED value STA MSPEED CALL MDINP ;clear garbage characters CALL MDINP CALL FRSTCR ;check for carrier the first time JC HANGUP2 ;wasn't a voice call ; ; ; Now test input for baud rate - FIRST, check for 300 bps. ; ANSWER ENDIF ;(NOT NORING) AND CALLBAK AND USRLOG ; IF (NOT NORING) AND CALLBAK ;continue w/callback routines JMP HANGUP2 ;go wait for next call ; EXPECT: LXI H,400 ;40 seconds to wait for second call ; RELOOK: CALL MDRING JNZ ANSWER ;yes, go B:CALL PATCH ;patch jump table CALL TSTBAUD ;see if bps=300 JZ WELCOME ;yes, exit ; ; ; Now check for 1200 bps ; CALL SET1200 ;now check 1200 bps JNZ ANS1 MVI A,BP1200 ;set the MSPEED pointer STA MSPEED CALL TSTBAUD ;check baud rate    JZ WELCOME ; ANS1: EQU $ CALL SET450 ;try 450 bps next JNZ ANS2 MVI A,BP450 ;set MSPEED pointer STA MSPEED CALL TSTBAUD ;check baudrate JZ WELCOME ; ANS2: EQU $ CALL SET600 ;try 600 bps now JNZ ANS3 MVI A,BP600 ;set MSPEED ST IF USRLOG AND PWRQD SHLD OLDUSR ;reset attempt counter ENDIF ;USRLOG AND PWRQD ; IF USRLOG SHLD NEWUSR ;reset logon counter ENDIF ;USRLOG ; IF USRLOG AND CALLBAK SHLD NONUSR ;reset voice counter ENDIF ;USRLOG AND CALLBACKA MSPEED CALL TSTBAUD ;check baudrate JZ WELCOME ; ANS3: EQU $ CALL SET710 ;try 710 bps (PMMI S-100 modems only) JNZ ANS4 MVI A,BP710 ;set MSPEED STA MSPEED CALL TSTBAUD ;check baudrate JZ WELCOME ; ANS4: EQU $ CALL SET110 ;final ; IF USRLOG AND IMSAI MVI A,0FFH OUT SENSE ;reset IMSAI panel display ENDIF ;USRLOG AND IMSAI ; IF USRLOG RET ENDIF ;USRLOG ; ; ; PRNLOG is called to print out the BYE version # and USRLOG info. It ; can be called from outsidly try 110 bps JNZ BADDO ;try again...*sigh* MVI A,BP110 STA MSPEED ;set MSPEED CALL TSTBAUD ;check baudrate JZ WELCOME ; BADDO: CALL UNPATCH ;restore original jump table JMP ANSWERA ;test more - invalid baud rate ; ; ; Get the console the program, using the vector after MCBOOT. ; PRNLOG: MVI C,PRINTF ;print out program version number LXI D,VMSG CALL BDOS ; IF USRLOG AND PWRQD ;print # of logon attempts MVI C,PRINTF LXI D,ATMSG CALL BDOS LXI H,OLDUSR+1 ;point to highe status when unpatched ; UCSTS: EQU $ ;get the console status when ; IF CPM2 MVI C,DRECTIO ;direct I/O call MVI E,0FFH ;ask for input CALL BDOS ;a=0 if no character waiting RET ENDIF ;CPM2 ; IF NOT CPM2 MVI C,CSTS ;in CP/M 1.4 byte CALL HXOUT ENDIF ;USRLOG AND PWRQD ; IF USRLOG ;print # of logons MVI C,PRINTF LXI D,SUMSG CALL BDOS LXI H,NEWUSR+1 CALL HXOUT ENDIF ;USRLOG ; IF USRLOG AND CALLBAK ;# of voice calls MVI C,PRINTF LXI D,VCMSG CALL , need the status first CALL BDOS ORA A RZ MVI C,CI ;and then the character CALL BDOS RET ENDIF ;NOT CPM2 ;..... ; ; ; Following are the usrlog routines ; IF USRLOG ;reset all logon counters RESET: LXI H,0 ENDIF ;USRLOG ; BDOS LXI H,NONUSR+1 CALL HXOUT ENDIF ;USRLOG AND CALLBACK ; RET ;if no log, null PRNLOG routine ;..... ; ; USRCHK: CALL PRNLOG ;give info MVI C,PRINTF LXI D,RS1MSG CALL BDOS ;prompt to resume waiting for ring ; PRNREL: CALL UCST  S ;get reply ORA A JZ PRNREL ;wait until answered STA OPTION ;save reply for later CPI 'T' ;is test requested JZ ANSWERB ;go to setup routine CPI 'R' ;is answer "r", for resume? JZ PRNRES ;go do it if so CPI 'R'+20H ;take lower caseIF USRLOG AND DECIMAL DAA ;decimal adjust ENDIF ;USRLOG AND DECIMAL ; IF USRLOG MOV M,A ;replace high order byte RET ENDIF ;USRLOG ;..... ; ; IF USRLOG HXOUT: PUSH H ;save pointer CALL HXHAF ;do high order half of # POP  too JNZ EXCPM ;if not "r", warm boot CP/M ; PRNRES: MVI C,PRINTF LXI D,RS2MSG JMP BDOS ;resume via BDOS after message ; ; ; Here to exit to CP/M, first reset the Smartmodem to default status ; EXCPM: CALL MDQUIT ;return Smartmodem to defauH ;restore pointer DCX H ;point to low, then do low half ; HXHAF: MOV A,M ;get half # in a MOV B,A ;save number RAR ;rotate right 4 bits RAR ;to make an ASCII digit RAR RAR CALL ONEOUT ;output MSN to console MOV A,B ;get number lt settings ; IF CCSDISK CALL DSKON ;turn on the drives ENDIF ;CCSDISK ; MVI A,0FFH STA WHEEL ;restore wheel byte for SYSOP MVI A,SMAXUSR STA MAXUSER ;and MAXUSR MVI A,SMAXDRV STA MAXDRIV ;and MAXDRIV JMP 0000H ;warm boot CP/back ; ONEOUT: ANI 0FH ;get LSN for output ADI 90H ;convert to decimal ASCII DAA ACI 40H DAA PUSH B MVI C,02H MOV E,A ;output the number CALL BDOS POP B RET ENDIF ;USRLOG ; ; ; Welcome to the system ; WELCOME:EQU $ ;welcM ; ; ; BOPLOG increments the 16 bit counter pointer at by HL. If the decimal ; option is n use, the number is kept as 4 BCD digits. ; IF USRLOG BOPLOG: MOV A,M ;get low byte INR A ;increment ENDIF ;USRLOG ; IF USRLOG AND DECIMAL Dome to the system ; IF CCSDISK CALL DSKON ;turn on the drives ENDIF ;CCSDISK ; IF CPM2 AND NOT USEZCPR MVI A,MAXUSR ;reset maximum user area STA MXUSR STA MAXUSER ENDIF ;CPM2 AND NOT USEZCPR ; IF NOT USEZCPR MVI A,MAXDRV ;rAA ;decimal adjust ENDIF ;USRLOG AND DECIMAL ; IF USRLOG MOV M,A ;replace low order byte RNC ;if no carry, bop done INX H ; else carry to high order byte MOV A,M ;get high order byte INR A ; and bop it ENDIF ;USRLOG ; eset maximum drive STA MXDRV DCR A STA MAXDRIV ENDIF ;NOT USEZCPR ; XRA A ;make sure line feeds are on again STA LFEEDS ; IF TIMEOUT MVI A,TOVALUE ;reset timeout count STA TOVAL ENDIF ;TIMEOUT ; MVI A,2 ;assume this many n  ulls in case of error STA NULLS ; IF LGONMSG LXI H,LOGMSG ;Logon message CALL ILPRT ;send this message ENDIF ;LGONMSG ; GETNULL:LXI H,NULMSG ;nulls message CALL ILPRT ;send this message CALL MINPUT ;get value MOV C,A ;to 'C' for es, done MOV C,A ;setup for type CALL MOUTPUT ;type the character CALL MSTAT ;check for character typed ORA A JZ WELTYLP ;no, loop CALL MINPUT ;yes, get character ENDIF ;WELFILE ; IF WELFILE CPI 'S'-40H ;CTL-S to delay listing?output CALL MOUTPUT ;echo character MOV A,C ;restore value CPI '0' JC GETNULL ;bad, retry CPI '9'+1 JNC GETNULL ;bad, retry SUI '0' ;make binary STA NULLS ;save count ; GETULC: LXI H,CRMSG ;Carriage Return, Line Feed CALL ILPRT  JNZ WELTYLP ;no, loop until EOF ; WAIT: CALL MSTAT ORA A ;has another char been typed? JZ WAIT ;no, wait CALL MINPUT ;yes, check character CPI 'C'-40H ;CTL-C to end listing? JNZ WELTYLP ;no, loop until eof ENDIF ;WELFILE ; ; ; ;send this message ; ; ; Print the welcome file ; IF WELFILE LXI H,WELFILN ;source LXI D,FCB ;destination MVI B,13 ;length CALL MOVE ;move the name LXI D,80H ;set DMA address to 80H MVI C,STDMA CALL BDOS ENDIF ;WELFILE ; IFGet the password ; PASSINT:EQU $ ;get the password ; IF PWRQD AND IMSAI AND SELPASS IN SENSE ;turn the switch up to require password ANI PWDSW JZ NOPASS ENDIF ;PWRQD AND IMSAI AND SELPASS ; IF PWRQD MVI D,3 ;3 tries at password ; CPM2 AND WELFILE MVI C,32 ;set user number for welcome file MVI E,WELUSR CALL BDOS ENDIF ;CPM2 AND WELFILE ; ; ; Open the welcome file ; IF WELFILE LXI D,FCB MVI C,OPEN CALL BDOS ; ; ; Did it exist? ; INR A ;A=> 0 means "no PASSINP:LXI H,PWMSG ;password message CALL ILPRT ;send this message LXI H,PASSWD ;point to password MVI E,0 ;no missed letters ; PWMLP: CALL MINPUT ;get a character CPI 60H ;lower case? JC NOTLC ;no, ANI 5FH ;make upper case alpha ;" JZ PASSINT ;no welcome file ; ; ; Got a file, type it ; XRA A ;A=0 STA FCBRNO ;zero record number LXI H,100H ;get initial buffer pointer ; ; ; Type the welcome file ; WELTYLP:CALL RDBYTE ;get a byte CPI 1AH ;EOF? JZ PASSINT ;y NOTLC: ENDIF ;PWRQD ; IF DUAL$IO AND PWRQD PUSH PSW ;save character input CPI 20H ;is character a control code? JNC PWDIS ;pass if displayable MVI C,'^' ;if control map to up arrow then display CALL CONOUT POP PSW PUSH PSW ADI   40H ; PWDIS: MOV C,A CALL CONOUT ;output character locally POP PSW ;restore 'A' reg. ENDIF ;DUAL$IO AND PWRQD ; IF PWRQD CPI 'U'-40H ;CTL-U? JZ PASSINP ;yes, abort, and retry CMP M ;match password? JZ PWMAT MVI E,1 ;no, show  ; IF COMFILE MVI A,20H ;fool the system so that the .COM file STA FCB+1 ; will see a space at FCB+1 for default LDA OPTION ; purposes. CPI 'A' ;SYSOP can bypass .COM file by typing JZ 0000H ; BYE /A CPI 'C' ;SYSOP can also go to .Cmiss CPI CR ;CR? JNZ PWMLP ;no, wait for CR ; ; ; Password did not match ; PWNMAT: LXI H,WRGMSG ;wrong password message CALL ILPRT ;send this message DCR D ;more tries? JNZ PASSINP ;yes JMP BADPASS ;no, go hang up ; ; ; Character OM file loaded JNZ RUNCOM ; with BYE /C LXI H,LSMSG ;loading System Message CALL ILPRT ;send this message: CALL LODCOM ; ; ; Everyone else gets com file ; RUNCOM: CALL 100H ENDIF ;COMFILE ; JMP 0000H ;warm boot now for "normal" CPmatched in password ; PWMAT: INX H ;to next character CPI CR ;end? JNZ PWMLP ;no, loop ; ; ; End of password. Any missed chars? ; MOV A,E ;get flag ORA A JNZ PWNMAT ;not right ENDIF ;PWRQD ; NOPASS: EQU $ ; IF USRLOG ;coun/M use ; ; ; TSTBAUD attempts to read a CR, LF or CTL-C and returns with zero flag ; if the character read is one of these three. ; TSTBAUD:CALL MINPUT ;get character from modem CPI CR ;if a CR RZ CPI LF ;if a LF RZ CPI 'C'-40H ;if a CTt number of successful logins LXI H,NEWUSR ;get last value CALL BOPLOG ;call routine to add one ENDIF ;USRLOG ; IF IMSAI AND USRLOG LDA NEWUSR ;re-get low order value CMA ;invert for lights OUT SENSE ;display on IMSAI front panel L-C RET ;return with proper flags set ;..... ; ; ; Test to see if carrier is there. If after CWAIT seconds, no carrier, ; then return, saying so. This routine is only called just after we as- ; swered the phone. ; FRSTCR: CALL MDCARCK ;carri ENDIF ;IMSAI AND USRLOG ; IF BOOTMSG LXI PLSMSG ;please wait message CALL ILPRT ;send this message ENDIF ;BOOTMSG ; IF COMFILE AND CPM2 MVI C,32 MVI E,COMUSR ;switch to .COM file user area CALL BDOS ENDIF ;COMFILE AND CPM2 er there? JNZ CARCK2 ;yes, jump to regular routine PUSH B ;save BC MVI B,CWAIT*10 ;set for "cwait" seconds JMP CARLP ;from here on, same as other routine ; ; ; Loss of connection test ; CARCK: CALL MDCARCK ;carrier there? JNZ CARCK2 ;ye  p, go onto other checks... PUSH B ;preserve so we can use it MVI B,CLOSS*10 ;set for 'CLOSS' seconds ; CARLP: CALL DELAY ;wait .1 seconds CALL MDCARCK ;check for carrier MOV A,B ;get count back in a POP B ;fix stack in case all is ok JNZ ;isolate user # RRC ;move to low bits RRC RRC RRC LXI H,MXUSR ;point to maximum user number CMP M ;valid user #? JC CARCK4 ;yes, don't change JZ CARCK4 LDA 0004H ;get login byte again ANI 0FH ;keep drive, zero user area STA 00 CARCK2 ;got carrier, continue on DCR A ;count time down STC ;in case this is the end of 'time' RZ ;return if timed out PUSH B ;preserve 'BC' MOV B,A ;get counter value in 'B' JMP CARLP ;keep checking ; ; ; Now test drive #'s and (i04H ;update login byte LXI H,IUMSG ;Invalid User message CALL ILPRT ;tell him what happened JMP 0 ;warm boot ENDIF ;CPM2 ; CARCK4: POP H ;restore 'HL' ORA A RET ;..... ; ; ; .1 sec delay routine ; DELAY: PUSH B LXI B,4167*MHZ f CP/M 2.x) user #'s to insure that maximums ; are not exceeded. ; CARCK2: EQU $ ; IF USEZCPR LDA MAXDRIV INR A STA MXDRV LDA MAXUSER STA MXUSR ENDIF ;USEZCPR ; IF NOT USEZCPR LDA MXDRV DCR A STA MAXDRIV LDA MXUSR STA MA;timing constant * clock MHz ; DELAY1: DCX B MOV A,B ORA C JNZ DELAY1 POP B RET ;..... ; ; ; 1 millisecond delay routine ; KDELAY: PUSH B LXI B,42*MHZ ;timing constant * clock MHz JMP DELAY1 ; ; ; Patch in the new JMP table (savingXUSER ENDIF ;NOT USEZCPR ; LDA 0004H ;check disk/user # ANI 0FH ;isolate drive PUSH H ;save 'HL' LXI H,MXDRV ;point to allowed # of drives CMP M ;valid drive? JC CARCK3 ;yes, skip this junk LDA 0004H ;get whole login byte ANI 0 the old) ; ; PATCH: CALL TBLADDR ;HL= CP/M BIOS jump table LXI D,VCOLDBT ;point to save location MVI B,24 ;save all vectors CALL MOVE ;move it LHLD VCONOUT+1 ;get the original CONOUT address SHLD COVECT ;store for use with XMODEM programsF0H ;retain user # & force drive to A: STA 0004H ;update login byte LXI H,IDMSG ;Incorrect Drive Message CALL ILPRT ;tell user what he did JMP 0000H ;warm boot ;..... ; ; CARCK3: EQU $ ; IF CPM2 LDA 0004H ;get login byte ANI 0F0H  ; ; ; Now move the new JMP table to CP/M ; CALL TBLADDR ;HL= CP/M BIOS jump table XCHG ;move it to 'DE' LXI H,NEWJTBL ;point to new jump table CALL MOVE ;move it RET ;..... ; ; UNPATCH:CALL TBLADDR ;HL= CP/M BIOS jump table XCHG    ;move to DE LXI H,VCOLDBT ;get saved table CALL MOVE ;move original table back ; IF LOSER LXI H,WMSTRT ;load old call location SHLD WBCALL+1 ;restore old call ENDIF ;LOSER ; RET ;..... ; ; ; Calculate HL=CP/M's jump table, B=lengtSCK LDA WRTLOC ;get write in progress flag ORA A RNZ ;busy, wait until done ENDIF ;RBBSCK ; CALL CARCK ;see if carrier still on RNC ;all ok ; ; ; Carrier is lost. Type message so local console shows the reason. ; Come come here oh ; TBLADDR:LHLD 1 ;get BIOS pointer DCX H ;skip to cold boot DCX H DCX H ; IF (NOT PRINTER) AND (NOT ALLDEV) MVI B,18 ;# of bytes to move ENDIF ;(NOT PRINTER) AND (NOT ALLDEV) ; IF PRINTER ;retain list device? MVI B,15 ;don'tn bad password. ; BADPASS:MVI A,1 ;show carrier lost - do not check again STA LOSTFLG LXI SP,STACK ;ensure valid stack LXI H,CLMSG ;carrier lost message CALL ILPRT ;Send this Message ; DROPCAR:LXI SP,STACK CALL UNPATCH ;restore original B move lister jump ENDIF ;PRINTER ; IF ALLDEV ;this patches all devices to phone MVI B,24 ;move all jumps ENDIF ;ALLDEV ; RET ;..... ; ; ; Move (HL) to (DE), length in (B) ; MOVE: MOV A,M ;get a byte STAX D ;put at new home IOS jump table XRA A ;clear out carrier lost flag STA LOSTFLG ; IF EXFILE MVI C,32 MVI E,EXUSR ;switch to exit .COM file user area CALL BDOS CALL LODEX CPI '*' ;test that file was really loaded JNZ 100H ;EXITFIL was't loaded, so runINX D ;bump pointers INX H DCR B ;decrement byte count JNZ MOVE ;if more, do it RET ;if not, return ;..... ; ; IF LOSER NWBCALL:CALL WMSTRT ;warm boot disk read CALL PATCH ;fix BIOS again after WMSTRT RET ENDIF ;LOSER ;..... it ENDIF ;EXFILE ; CALL UNPATCH JMP HANGUP ; ; ; Readbyte routine - used to read the welcome file ; IF WELFILE RDBYTE: MOV A,H ;time to read? ORA A ;if at 100H, no read required JZ NORD ; ; ; Have to read a sector ; LXI D,FCB ; ; ; Common routine to check for carrier lost - called from console out ; CHECK: EQU $ ;check for carrier lost ; IF MINICK LDA IOBYTE ;get IOBYTE ANI 80H ;test for disk update RET ;busy, wait until done ENDIF ;MINICK ; IF RBB MVI C,READ CALL BDOS ORA A ;ok? MVI A,1AH ;fake up EOF RNZ ;return EOF if bad LXI H,80H ; NORD: MOV A,M ;get character INX H ;point to next byte RET ENDIF ;WELFILE ; ; ; Keyboard/modem status test routine ; MSTAT: EQU $   ; IF BYELOW CALL BDCHEK ;if BYELOW, set 6 to safety ENDIF ;BYELOW ; CALL CHECK ;check for carrier lost ; IF DUAL$IO ;want local console? CALL CONSTAT ;get local status ORA A RNZ ;return if local character ENDIF ;DUAL$IO ;L$IO ;both local and remote CALL CONSTAT ;check local console ORA A ;character? JNZ CONIN ;yes, read it & return ENDIF ;DUAL$IO ; ; ; Local console wasn't ready, so read modem ; CALL MDINP ANI 7FH ;delete parity JZ MINPUT ;ignor CALL MDINST ;get modem input status RET ;..... ; ; ; Modem input function, checks local console first ; MINPUT: EQU $ ; IF BYELOW CALL BDCHEK ENDIF ;BYELOW ; IF RKEYS LDA BYTEB ORA A JNZ CAP ENDIF ;RKEYS ; IF TIMEOUe nulls ; IF HARDLOG PUSH B MOV B,A ;put a copy of the character in b LDA HARDON ;if HARDON=0 then turn HARDLOG off (so ORA A ;..SYSOP does not waste paper while he MOV A,B ;..playing ZORK from work.) POP B JZ NOLOG ; CPI 20H JNCT LDA TOVAL ;get # of minutes before timeout ; MINPUT0:STA TOCNTM ;set minutes counter PUSH H LXI H,42000 ;initialize one minute timeout counter SHLD TOCNT POP H ENDIF ;TIMEOUT ; MINPUT1:LDA LOSTFLG ;known loss of carrier? ORA A  MINPUT3 CPI CR JNZ NOLOG ; MINPUT3:CALL LISTOUT ;echo on printer CPI CR JNZ NOLOG ;return needs linefeed MVI A,LF CALL LISTOUT ;so send it MVI A,CR ;get back CR ENDIF ;HARDLOG ; NOLOG: IF RKEYS PUSH H PUSH D PUSH B PUSHCZ CHECK ;carrier still on? CALL MSTAT ;anything? ORA A ; IF NOT TIMEOUT JZ MINPUT ;loop til character received ENDIF ;NOT TIMEOUT ; IF TIMEOUT JNZ MINPUT2 CALL KDELAY ;wait 1 ms PUSH H LHLD TOCNT ;knock down timeout counter PSW CPI ' ' JNC NOLOG2 MOV E,A ;save char ADD E ;A*3 (3 bytes per table entry) ADD E MOV E,A MVI D,0 LXI H,TABLE DAD D INX H ;increment past dummy jump op code MOV E,M INX H MOV D,M XCHG MOV A,H ORA L JZ NOLOG2 SHLD  DCX H SHLD TOCNT MOV A,H ORA L POP H JNZ MINPUT1 ;still time left, keep trying LDA TOCNTM ;count off last minute DCR A JNZ MINPUT0 ;go back if time left LXI H,ITOMSG CALL ILPRT JMP NOSLASH ENDIF ;TIMEOUT ; MINPUT2: IF DUABYTEA MVI A,1 STA BYTEB POP PSW POP B POP D POP H ; CAP: PUSH H PUSH D PUSH B LHLD BYTEA MOV A,M INX H SHLD BYTEA ORA A JNZ NL2 XRA A STA BYTEB POP B POP D POP H JMP MINPUT ; NL2: POP B POP D POP H JMP NL22   ; NOLOG2: POP PSW POP B POP D POP H ; NL22: ENDIF ;RKEYS CPI 3 ;is it ^c? RNZ ;no, pass it through LDA 0 ;see if warm boot disabled CPI 0C3H ;jump means warm boot ok MVI A,3 ;so return with a ^C RZ MVI A,CTRLC ;else conveIF ;OXGATE ; CALL MDOUTP ;output character to modem ; SILENT: EQU $ ; IF DUAL$IO ;to local console too? PUSH PSW ;save character CALL CONOUT ;send to regualr BIOS POP PSW ;get character again ENDIF ;DUAL$IO ; ; ; Check for nulrt to different character RET ;..... ; ; ; Modem output function ; MOUTPUT:EQU $ ; IF BYELOW CALL BDCHEK ENDIF ;BYELOW ; ; ; If we already know carrier is lost, do not check for it again or loop ; trying to output. ; LDA LOSTFLG ls ; CPI LF ;time for nulls? RNZ ;no, return ; ; ; Send nulls if required ; LDA NULLS ;get count ORA A ;any? RZ ;no PUSH B MOV B,A ;save count MVI C,0 ;0 is a null ; NULLP: CALL MOUTPUT ;type a null DCR B ;another? JNZ;known loss of carrier? ORA A JNZ SILENT ;avoid loop in case carrier lost CALL CHECK ;carrier still on? ; MOUTA: CALL MDOUTST ;check modem output status JZ MOUTA MOV A,C ;get character ANI 7FH ;strip parity bit ; IF OXGATE CPI 60H  NULLP ;yes, loop POP B MVI C,LF ;now, send a LF RET ;..... ; ; ; Boot trap - becomes disconnect if JMP at 0 has been altered ; MBOOT: LDA 0 ;look at opcode CPI 0C3H ;is it still a jmp? JNZ NOSLASH ;no, so say bye bye... ; ; ; Speci ;check for lower case JC MOUTP2 ;skip if not lower case CPI 7FH ;check for rubout JZ MOUTP2 PUSH H LXI H,ULCSW ;subtract either 20H or nothing SUB M POP H MOV C,A ;force on local as well as remote ; MOUTP2: CPI LF ;we have a toggle al warm-boot routine - print a message or something - even run a ; program if you want to!!! ; WMBMSGPRT:EQU $ ; IF WBRTN PUSH B PUSH D PUSH H ; IF PRNTWB LXI H,WBMSG CALL ILPRT ;print the following message: ENDIF ;PRNTWB ; POfor line feeds JNZ MOUTP3 ;nope, not a LF LDA LFEEDS ;yes, see if we can send it... ORA A ;set flags MVI A,0 ;prepare with a null JNZ MOUTP3 ;nope, don't (instead, send a null) MVI A,LF ;yes, it's ok to send the line feed ; MOUTP3: ENDP H POP D POP B ENDIF ;WBRTN ; JMP VWARMBT ;go do a warm boot ;..... ; ; ; Inline print routine ; ; The following code has been modified to accomodate the automatic ; loader. (The loader may modify a constant, so all messages have ; b  een placed at the end of the program and just moved to high memory.) ; ILPRT: PUSH B ;save BC ; ILPLP: MOV C,M ;get character CALL MOUTPUT ;output it INX H ;point to next character MOV A,M ;test for end of message ORA A JNZ ILPLP POP Bf-memory) PUSH D ;resave for next time MOV A,E ;subtract: (top) - (address) SUB L MOV A,D ;only the carry needed SBB H JNC SIZEOK ;CY=better MOVCPM LXI D,PTSMSG JMP ERRXIT ; SIZEOK: INX B PUSH B PUSH H ;save TPA address XCHG  ;restore BC RET ;return past message ;..... ; ; ; Routine to load the com file ; LODCOM: EQU $ ;routine to load the .COM file ; IF COMFILE LXI H,COMFCB SHLD CURRFCB XRA A ;initialize FCB STA COMFCB LXI H,COMFCB+12 MVI B,21 C;align registers MVI C,STDMA ;tell BDOS where to put record CALL BDOS LHLD CURRFCB ;point to aprropriate FCB XCHG MVI C,READ CALL BDOS ORA A JZ GLOOP ;a=0 if more to read POP B ;unjunk stack POP B ;this is our counter POP H ;morALL ZLOOP LXI D,COMFCB CALL OPENFIL JZ ABORT JMP LOADFIL ENDIF ;COMFILE ; LODEX: IF EXFILE LXI H,EXFCB SHLD CURRFCB LXI H,EXFCB+12 MVI B,21 CALL ZLOOP LXI D,EXFCB CALL OPENFIL MVI A,'*' ;do not try to run unloaded file RZe junk on stack MOV A,B ;check for zero ORA C JZ ABORT ;we should have read something LXI D,80H ;we did, reset DMA to 80H MVI C,STDMA CALL BDOS LXI D,CFLMSG LDA OPTION ;see if this was "BYE /C" CPI 'C' ;if yes, do not print message  ;cannot open file, finish BYE hangup ENDIF ;EXFILE ; ; ; Now load the file ; IF COMFILE OR EXFILE LOADFIL:LHLD 6 ;get top of memory LXI D,-80H DAD D PUSH H ;save on stack LXI D,80H ;TPA-80H LXI B,0 ;keep a record counter PUS RZ MVI C,PRINTF CALL BDOS RET ;..... ; ; ZLOOP: MVI M,0 INX H DCR B JNZ ZLOOP RET ;..... ; ; OPENFIL:MVI C,OPEN ;open file pointed to by 'DE' CALL BDOS INR A RET ;..... ; ; ABORT: LXI D,CNFMSG ; ERRXIT: MVI C,PRINTF CAH B ;save counter PUSH D ;and load address ; GLOOP: POP D ;get TPA address LXI H,80H ;point to next address to read to DAD D ;HL has the address POP B ;increment the counter ; ; ; Check for load past top-of-memory ; POP D ;get (top-oLL BDOS ;print the abort message JMP EXCPM ;warm boot ENDIF ;COMFILE OR EXFFILE ; ; ; This area is used for vectoring calls to the user's CBIOS, but saving ; the registers first in case they are destroyed. ; CONSTAT:PUSH B PUSH D PUSH H    CALL VCONSTAT POP H POP D POP B RET ;..... ; ; CONIN: PUSH B PUSH D PUSH H CALL VCONIN ; IF FKEYS CALL CKFUNC ENDIF ;FKEYS ; POP H POP D POP B RET ;..... ; ; CKFUNC: IF FKEYS AND IMSAI PUSH B MOV B,A ;save  ; LISTOUT:PUSH B PUSH D PUSH H PUSH PSW ; IF BYELOW CALL BDCHEK ENDIF ;BYELOW ; MOV C,A CALL VLISTOUT POP PSW POP H POP D POP B RET ;..... ; ; IF BYELOW BDCHEK: PUSH H ;to make truly universal, (???) this DB LXIcharacter IN SENSE ;read the switches (tea leaves?) ANI ENABLF ;check function key enable switch MOV A,B ;get character POP B RZ ;no function key if switch off ENDIF ;FKEYS AND IMSAI ; IF FKEYS CPI BLNKKEY ;turn off caller's outpH ; program always re-stores the BDOS ; BDADDR: DW 0000H ; pointer at 6&7 set up location for SHLD 6 ; beginning address of CONSOLX CTL ; at every chance. This replaces the POP H ; WMLOCK & OLDBD as in BYE2 AND BYE3 RET ENDIF ;But for a moment? JZ BLNKTOG ;(this is a toggle) CPI SYSDKEY JZ SYSDOWN ;tell caller to leave in 5 minutes CPI TWITKEY JZ DROPCAR ;hang up on the twit CPI MSGKEY RNZ LXI H,MFSMSG ;SYSOP message CALL ILPRT ;tell caller you want to say sYELOW ;..... ; ; ; This is the jmp table which is copied on top of the one pointed to by ; location 1 in CP/M. ; NEWJTBL:JMP MCBOOT ;cold boot JMP MBOOT ;warm boot JMP MSTAT ;modem status test JMP MINPUT ;modem input routine JMP MOUTPUT omething MVI A,' ' RET ;..... ; ; SYSDOWN:LXI H,SGDMSG ;system going down message CALL ILPRT ;send this message MVI A,' ' RET ;..... ; ; BLNKTOG:LDA LOSTFLG ORA A ;if zero, make 0FFH MVI A,0FFH ;(we do not use CMA, because LOSTFLG  ;modem output routine ; IF NOT ALLDEV RET ;dummy list device NOP NOP ENDIF ;NOT ALLDEV ; IF ALLDEV JMP MOUTPUT ;modem list device JMP MOUTPUT ;modem punch device JMP MINPUT ;modem reader device ENDIF ;ALLDEV ; IF CCS JZ BLNKT1 ; could equal a different value like 1) XRA A ;if not zero, make it zero ; BLNKT1: STA LOSTFLG MVI A,' ' RET ; ENDIF ;FKEYS ;..... ; ; CONOUT: PUSH B PUSH D PUSH H CALL VCONOUT POP H POP D POP B RET ;..... ;DISK DSKON: PUSH PSW ;save 'A' and flags MVI A,DISKON ;turn on motors OUT DISK PUSH H ;now, wait a long time LXI H,0000K ; DSKLP: XTHL XTHL DCX H ;count loop MOV A,H ;check if done? ORA L JNZ DSKLP POP H ;restore HL POP PSW ;  and 'A' and flags RET ; DSKOFF: PUSH PSW ;save 'A' and flags MVI A,DISKOFF ;turn motors off OUT DISK POP PSW RET ENDIF ;CCSDISK ;..... ; ; ; The 'JMP' instructions in the remote control keys are necesary for the ; relocation routinestended operation. ; SMINIT: CALL SET300 ;program commences looking for 300 bps CALL SMSEND ;go send smartmodem reset DB 'AT Z',CR,0 ;reset modem to standard default CALL SMSEND ;go initialize the modem DB 'AT Q1 E0 M0 S2=128 S0=2',CR,0 CALL  to relocate the address. ; IF RKEYS TABLE: JMP 0 JMP DIR ;^A JMP DIR2 ;^B JMP 0 JMP 0 JMP 0 JMP FIND ;^F JMP GBYE ;^G JMP 0 JMP 0 JMP 0 JMP 0 JMP LTYPE ;^L JMP 0 JMP 0 JMP 0 JMP 0 JMP 0 JMP RBBS ;^R JMP 0 DLP ;delay routine RET ;... ; ; ; Actually, the above string can vary somewhat (e.g. you may want to ; leave the speaker on, you may want to inhibit codes/text, etc. Those ; items are all optional. ; ; ; E0: Do not echo characters in command  JMP TYPE ;^T JMP 0 JMP 0 JMP NEW ;^W JMP 0 JMP LCRCK ;^Y JMP CRCK ;^Z JMP XMDM ;^[ JMP 0 JMP LDIR ;^] JMP CHAT ;^^ JMP 0 ENDIF ;RKEYS ;..... ; ; ;***********************************************************************state ; ; M0: Do not turn the loud speaker on ; ; S0: This is the number of times the phone can ring before ; the SmartModem answers. A value of 0 means "do not ; answer." Once you are ready to receive, S0=2 will ; let it answer on the second ; ; $$$$ Smartmodem insert for BYE3 - 01/01/84 $$$$ ; IF SMODEM ; ; SWITCH SETTINGS: 1 2 3 4 5 6 7 8 ; ; HAYES Smartmodem 300/1200 -- UP UP DN UP DN UP UP DN ; US Robotics Auto-Dial 212 -- UP UP UP UP ; ; ; The following rout ring. ;..... ; ; ; Delay about two seconds to let modem get stabilized before or after a ; command string. ; DLP: MVI B,20 ;wait about two seconds to "be sure" ; DLP1: CALL DELAY DCR B JNZ DLP1 RET ;..... ; ; ; (This routine is not neeines are patterned after work originally done by Don ; Brown. ; ; Initialize the Smartmodem. First, disable the auto-answer to prevent ; any problems if somebody phones while you are resetting the registers. ; Then reset the registers for normal unatded with the current SMINIT routine.) ; SMANSW: RET CALL SMSEND ;send following message to modem DB 'A',CR,0 ;answers the phone RET ;..... ; ; ; DE-INITIALIZE THE SMARTMODEM ; ; When the operator uses CTL-C followed by anything but "R", this   call ; will drop the 'AA' and return the Smartmodem to default settings. ; SMQUIT: CALL SMSEND ;send following message to modem DB 'AT Z',CR,0 ;reset modem to standard default CALL DLP ;insure command line is completed RET ;..... ; ; ; Sendill only handle 300 bps.) ; ;======================================================================= ; ; 01/08/84 Original version - John Riehl 1-713-644-7070 days ; 1-713-488-1257 evenings ; ;============================================= a command string to the Smartmodem (similar to ILPRT) ; SMSEND: XTHL ;save HL, get address of message CALL DLP ;allow modem to stabilize PUSH B ;save 'BC' registers ; SMPLP: CALL MDOUTST ;modem ready for character? JZ SMPLP ;no, go check a========================== ; Changes to main BYE3 program ; ; Find these lines in the main BYE3 program: ; ; START: LXI SP,ISTACK ;set stack for initialization routine ; ; ; IF BYELOW ; CALL MDCARCK ;check to see if BYE3 is alreagain MOV A,M ;get the character OUT DATPORT ;Send the character INX H ;point to next MOV A,M ;Get next character ORA A ;Has all been sent JNZ SMPLP ;no, go send another character POP B ;restore the BC registers XTHL RET ;return pdy loaded ; ; Then replace them with the following lines: ; ; OSBORNE:EQU YES ; ; START: LXI SP,ISTACK ;set stack for initialization routine ; ; ; IF BYELOW ; ; ; IF NOT OSBORNE ; CALL MDCARCK ;check to see if BYE3 is already loaast end of message ;..... ; ; ENDIF ;SMODEM ; ; End of Smartmodem insert ;*********************************************************************** ; ; ++++ INSTALL YOUR MODEM CONTROL PATCHES HERE ++++ ; ;*****************************ded ; ENDIF ;NOT OSBORNE ; ; ; IF OSBORNE ;relocate GETSTAT and MDINP ; LXI H,GETSTAT ;above 4000H ; LXI D,4000H ; LXI B,MDOUTP-GETSTAT ; DB 0EDH,0B0H ;Z80 LDIR ; CALL 4000H ; PUSH PSW ; ANI DCD ; CNZ 4000H+MDINP-GETSTA****************************************** ; ;B3OSCP-3.ASM Osborne 01 - COMM-PAC modem insert for BYE3 ; ; This version is for the Osborne 01 hooked up to an Osborne COMM-PAC ; modem. The COMM-PAC can detect a ring, so set NORING to 'NO'. (It ; wT ; POP PSW ; CMA ; ANI DCD ; ENDIF ;OSBORNE ; ; ; ; End of changes to the main BYE3 program ; (be sure to set Smodem equate to 'NO'.) ;======================================================================= ; ; ; The following defi  ne the port address to use. ; BASEP: EQU 2A00H ;Modem base port DATPORT:EQU BASEP+1 ;Data port STPORT: EQU BASEP ;Status/Control port ; ; ; The following are STPORT commands (out these to STPORT) ; MODINS: EQU 01010110B ;8 bits, no parity, 1 stONINS CALL SETSPD CALL UDELAY MVI B,6BH MVI A,RSTINS ;reset the ACIA CALL SETSPD CALL UDELAY MVI A,ONINS ;RTS so that modem can answer phone CALL SETSPD POP B ;restore BC RET ;return ;..... ; ; ; The following routine sets RTS hop bit, 64x OFFINS: EQU 00010110B ;drop RTS to go off hook ONINS: EQU MODINS ;send RTS RSTINS: EQU 00000011B ;reset ACIA ; ; ; The following are STPORT status masks ; DAV: EQU 00000001B ;data available DCD: EQU 00000100B ;data carrier detect FE:igh to turn off the modem when done. ; MDQUIT: CALL MDINIT XRA A RET ; ;..... ; ; ; The following routine will make the modem answer the phone. It should ; also set 300 bps. ; MDANSW: MVI A,OFFINS ;turn off RTS, etc. CALL SETSPD RET ;r EQU 00010000B ;framing error OE: EQU 00100000B ;overrun error ERR: EQU OE+FE ;overrun and framing error PE: EQU 01000000B ;parity error TBMT: EQU 00000010B ;transmitt buffer empty ; ; ;==============================================================eturn ;..... ; ; ; The following is a routine to determine if there is a character wait- ; ing to be received, if none, the Zero flag will be set, otherwise it ; returns with FF in register A. Remember that the system will like you ; a little more========= ; ; If any of your routines zaps anything other than the Accumulator, then ; you must preserve all other registers. ; ;======================================================================= ; ; ; This routine should turn off everything o if you also mask out framing, parity, and overrun errors. ; MDINST: CALL GETSTAT ;get status ANI DAV ;got a character? RZ ;return if none CALL GETSTAT ;get status again ANI ERR ;check for framing and overrun JZ MDINST1 ;no errors CALLn the modem, and get it ready ; to wait for a ring. (Also hang it up.) ; MDINIT: PUSH B MVI C,3 ; CNT: MVI B,6BH MVI A,ONINS CALL SETSPD CALL UDELAY MVI B,6BH MVI A,OFFINS CALL SETSPD CALL UDELAY DCR C JNZ CNT MVI B,6BH MVI A, MDINP ;reset error flags XRA A ;return false RET ; MDINST1:MVI A,0FFH ;we have a character ORA A RET ;..... ; ; ; The following is a routine to determine if the transmit buffer is ; empty. If it is, it will return with the Zero flag cle  ar. If the ; transmitter is busy, then it will return with the Zero flag set. ; MDOUTST:CALL GETSTAT ANI TBMT RET ;..... ; ; ; The following is a routine that will check to make sure we still have ; carrier. If there is no carrier, it will rehese next routines set the proper baud rates for the modem. If you ; do not support the particular rate, then simply put in a JMP to ; SETINV. If the baud rate change was successful, make SURE the Zero ; flag is set. ; ; The following routine returnturn with the Zero flag ; set. It will also check to see if the phone is ringing. If not, it ; will return with the Zero flag set, otherwise it will be cleared. ; MDRING: MDCARCK:CALL GETSTAT ;get status PUSH PSW ANI DCD ;if carrier is off Cs a 255 because we were not able to set to ; the proper baud rate because either the serial port or the modem can't ; handle it. ; SET110: SET450: SET600: SET710: SET1200: SETINV: MVI A,0FFH ORA A ;make sure the Zero flag isn't set RET ; ;.NZ MDINP ;then reset DCD POP PSW CMA ANI DCD ;check if carrier is on RET ;..... ; ; ; Get ACIA status ; GETSTAT:DI OUT 0 LDA STPORT OUT 1 EI RET ;..... ; ; ; The following is a routine that will input one character from the ;.... ; ; ; The Osborne COMM-PAC will only operate at 300 baud ; ; Set up for 300 bps ; SET300: XRA A ;load 300 bps RET ;..... ; ; SETSPD: DI OUT 0 STA STPORT OUT 1 EI XRA A RET ;... ; ; ; Delay ; UDELAY: DCR B JNZ UDELAY  modem port. If there is nothing there, it will return garbage... ; so use the MDINST routine first. ; MDINP: DI OUT 0 LDA DATPORT ;get character OUT 1 EI ANI 7FH ;strip parity and other garbage RET ;..... ; ; ; The following is a rou RET ;..... ; ; ; Ok, that's all of the modem dependent routines that BYE3 uses, so if ; you patch this file into your copy of BYE3, it should work out well. ; ;************************************************************************ ;* END Otine that will output one character in register ; A to the modem. REMEMBER, that is register A, not register C. ; ; ** Use MDOUTST first to see if buffer is empty ** ; MDOUTP: DI OUT 0 STA DATPORT ;send it OUT 1 EI RET ;..... ; ; ; TF OSBORNE PATCH CODE ;************************************************************************ ; ENDOBJ: EQU $ ; IF RKEYS CHAT: DB 'CHAT',0 CHEK DB 'CHEK ',0 DIR: DB 'DIR',CR,0 DIR2: DB 'DIR *.* $',0 FILE: DB 'FILE ',0 GBYE: DB 'BYE'  ,0 LDIR: DB 'LDIR ',0 LTYPE: DB 'LTYPE ',0 NEW: DB 'WHATSNEW',0 RBBS: DB 'RBBS',0 TYPE: DB 'TYPE ',0 XMDM: DB 'XMODEM ',0 ENDIF ;RKEYS ; ;----------------------------------------------------------------------- ; ; Program version number messF PWRQD PASSWD: DB 'DDT' ;the password itself DB CR ;end of password, CR-only to erase it ; ; ; (Allow room for larger password to be entered) ; DB 0,0,0,0,0,0,0 ; PWMSG: DB CR,LF,'Enter Password: ',0 WRGMSG: DB 'Incorrect password',CR,LF,0 age. ; VMSG: DB CR,LF,'BYE',MAIN+'0',' v' DB VERS/10+'0','.',VERS MOD 10+'0',' - ' DB MONTH/10+'0',MONTH MOD 10+'0','/' DB DAY/10+'0',DAY MOD 10+'0','/' DB YEAR/10+'0',YEAR MOD 10+'0',CR,LF,'$' ; NULMSG: DB CR,LF,'Nulls, if needed, (0-9)? ',0  ENDIF ;PWRQD ; IF BOOTMSG PLSMSG: DB CR,LF DB 'Please Wait... ' ;boot message goes here DB CR,LF,0 ENDIF ;BOOTMSG ; IF COMFILE LSMSG: DB 'Loading system...',CR,LF,0 ENDIF ;COMFILE ; IDMSG: DB '++ Invalid drive, returning to A:; CRMSG: DB CR,LF,CR,LF,0 ; IF PRNTGB GBMSG: DB CR,LF,' Good-bye, call again...' DB CR,LF,CR,LF,0 ENDIF ;PRNTGB ; RS1MSG: DB CR,LF,'Type "R" to resume, anything else to ' DB 'warm boot: $' ; RS2MSG: DB 1AH,'Resuming...',CR,LF,'$' ;  ++',0 ; IF CPM2 IUMSG: DB '++ Invalid user number, returning to 0 ++',0 ENDIF ;CPM2 ; CLMSG: DB CR,LF,'[Carrier Lost]',CR,LF,0 ; IF TIMEOUT ITOMSG: DB '[Input timed out]',7,0 ENDIF ;TIMEOUT ; IF FKEYS MFSMSG: DB 'Message from SyIF USRLOG AND PWRQD ATMSG: DB CR,LF,'Number of logon attempts: $' ENDIF ;USRLOG AND PWRQD ; IF USRLOG SUMSG: DB CR,LF,'Number of logons: $' ENDIF ;USRLOG ; IF USRLOG AND CALLBAK VCMSG: DB CR,LF,'Number of voice calls: $' ENDIF ;USsop:',0 SGDMSG: DB 'System is going down....' DB 'please use BYE to log-off, thank you',0 ENDIF ;FKEYS ; LFMSG: DB CR,LF,CR,LF,0 ; IF PRNTWB WBMSG: DB CR,LF,'Booting CP/M... ',CR,LF DB 0 ENDIF ;PRNTWB ; IF COMFILE OR EXRLOG AND CALLBAK ; IF LGONMSG LOGMSG: DB 'Baudrate determined by your input (300/1200 bps)',CR,LF DB 'Send several C/R''s to set baudrate....',CR,LF,0 ENDIF ;LGOMSG ; ; ; Access password (ends in carriage return) - keep password here ; IFILE PTSMSG: DB '++ Program area too small! ++',7,'$' CNFMSG: DB CR,LF DB '++ Cannot find .COM file ++',7,'$' CFLMSG: DB CR,LF,'[ COM file loaded ]',CR,LF,'$' ENDIF ;COMFILE OR EXFILE ; IF WELFILE WELFILN:DB 0,'WELCOME ' ;welcome file nam  e, must be 11 chars. DB 0 ENDIF ; IF COMFILE COMFCB: DB 0,'RBBS COM' ;.COM file name, must be 11 chars. DS 21 ;rest of .COM FCB ENDIF ;COMFILE ; IF EXFILE EXITFCB:DB 1,' COM' ;exit filename, must be 11 chars. DS 21 ;rest of exit fcb ENDIF ;EXFILE ; ; ; These areas are not initialized ; PEND: EQU $ ;The following area is not initialized ; IF COMFILE OR EXFILE CURRFCB:DS 2 ENDIF ;COMFILE OR EXFILE ; OPTION: DS 1 TOCNTM: DS 1 TOCNT: DS 2 ; ; ; Save the CP/M jump table here ; VCOLDBT: DS 3 VWARMBT: DS 3 VCONSTAT:DS 3 VCONIN: DS 3 VCONOUT: DS 3 VLISTOUT:DS 3 VPUNCH: DS 3 VREADER: DS 3 ; ; ; Since these areas are not initialized, the following counters will not ; be changed by subsequent loads of this program ; IF USRLOG OLDUSR: DS 2 NEWUSR: DS 2 NONUSR: DS 2 ENDIF ;USRLOG ; IF RKEYS BYTEA: DW 0 BYTEB: DB 0 ENDIF ;RKEYS ; DS 60 STACK: EQU $ ;local stack OBJEND: EQU $ ;..... ; ; END ; 03/14/84 ; - modified by Roy Robinson for pagination pause ; - added conditional equates for "secure" cp/m systems utilizing ; maxuser and maxdriv bytes, "secure" cp/m systems have intrinsic ; commands deleted out of ccp rather than using zcpr/nzcpr/zcmd ; FILE.ASM ; ; This program will search all user areas of all drives for any files ; matching the request on the command line. (The maximum user area can ; be limited by changing the 'MAXUSR' equate for use on RCPM systems.) ; It then d  isplays those files. Allowable user areas for CP/M are 0-15. ; Originally written by R. Rodman. ; ; Example: FILE *.COM lists all .COM files on all drives and ; all allowable areas (set by default to ; show through user 15.) ; ; FI modem) ; ; 11/08/83 Returned to standard BDOS call for select disk. This re- ; v18 moves the Bios trap and requires setting MAXDRV and MAXUSR ; to your hardware environment. This fixes the problem with ; the FILE bombing after a CTL-LE displays short help message ; ; ; Please return any updates to technical CBBS Dearborn MI (313) 846-6127 ; so the file will be available to all. ; ; ;======================================================================= ; ; 02/27/84 RS, CTL-C sequence. ; - Wayne Masters Potpourri SYSOP ; (408) 378-7474 (300/1200 modem) ; ; 10/17/83 Added USEMAX equate and supporting code to allow a RBBS ; v17 SYSOP to dynamically change the users access privledges ; based on theformatted, standardized tabs, minor changes, ran through ; v21 FILTX and TABASM, saving 19 sectors of source code length. ; - Irv Hoff ; ; 01/14/84 Fixed bug in user area search limit when USEMAX true. When ; v20 using ZCMD/NZCPR, loe user status--(normal, special, twit, SYSOP, ; etc.) Other BBS software should set the USRMAX (03FH) and ; DRIVMAX (03DH) to the allowed values. These changes work ; in the same way XMODEM76, SD-72, and BYE17 do. ; - Wayne Masters Potcation 03FH contains Max. user area +1, ; and FILE was using this as absolute limit. ; - Mark Howard CNY Tech RCP/M SYSOP ; (315)-437-4890 (300 modem) ; ; 12/14/83 Fixed bug in NONAME routine where instead of returning to ; v19 CPpourri SYSOP ; (408) 378-7474 (300/1200 modem) ; ; 06/01/83 Added "searching..." to show the reason for no activity on ; v14 longer searches. Revised one of the exit routines. Other ; minor changes. - Irv Hoff ; ; 02/13/83 Now pr/M, the program would continue on to search for files. ; Returned equates to default values as per version 16. (No ; need for most users to obtain source code, then reassemble.) ; - Ed Svoboda Oracle HQ SYSOP ; (408) 732-9190 (300/1200ints a normal display for drive/user area while keep- ; v13 ing normal column width for justification. Several other ; minor changes. Always starts at first disk, User 0, regard- ; less of the current disk or user number. It then returns!   to ; the present drive and user area. ; - Irv Hoff ; ; 02/02/82 Enabled program to look at a specific number of drives in ; v12 the event the BIOS 'illegal drive select' is not included. ; - Larry Clive ; ;======================== LF: EQU 10 ;ASCII linefeed TBUF: EQU BASE+128 ;DMA buffer address prints equ 9 ;..... ; ; ; DEFINE SOME BDOS FUNCTIONS: ; CONIN: EQU 1 ;console input function CONOUT: EQU 2 ;console output function PRINT: EQU 9 ;print string at console func=============================================== ; ; ; DEFINE TRUE AND FALSE ; YES: EQU 0FFH NO: EQU 0 ;..... ; ; ; SET THE FOLLOWING AS DESIRED: ; SHOWSYS:EQU no ;'YES' if want to show system files DRVTYP: EQU no ;'YES' if BIOS has 'ILLEGAL tion CONSTAT:EQU 11 ;get console status function RTNVER: EQU 12 ;return version number function SELDRV: EQU 14 ;select drive SRCHFST:EQU 17 ;search for first function SRCHNXT:EQU 18 ;search for next function SETIOB: EQU 24 ;set I/O byte SETDMADRIVE SELECT' ;trap set 'NO' if no trap in BIOS, ;then set 'MAXDRV' to number of drives to ;search through for the requested file. MAXDRV: EQU 4 ;number of drives to search through MAXCOL: EQU 3 ;max number of columns desired in display : EQU 26 ;set DMA address function SETUSR: EQU 32 ;set/get user code function ;..... ; ; ORG BASE+256 ; ; START: LXI H,0 ;set 'HL' to zero DAD SP ;get stack pointer into 'HL' SHLD STACK ;save for exit to 'CCP' stack LXI SP,STACK ;set  MAXUSR: EQU 1 ;max user # to be checked (0-15 possible) USEMAX: EQU yes ;'YES' for dynamic changes USRMAX: EQU 03FH ;location of MAXUSER byte DRIVMAX:EQU 03DH ;location of MAXDRIV byte nzcpr: equ no ;set to yes if using nzcpr or zcmd ; ;set tup local stack CALL ILPRT ;print sign-on message DB CR,LF,'FILE version 21a - ^X to abort',CR,LF,0 LDA FCB+1 ;check for filename on command line CPI ' ' JZ NONAME CALL ILPRT DB 'searching...',0 ; SETUP: LDA 0004H ;save user/drive # STo no if using "secure" cp/m ;..... ; ; ; DEFINE SOME MISCELLANEOUS VALUES: ; BASE: EQU 0 ;set to base address of your cp/m BDOS: EQU BASE+5 ;CP/M BDOS entry point CR: EQU 13 ;ASCII return FCB: EQU BASE+5CH ;CP/M file control block address A UDNUM RRC ;1st 4 bits give current user # RRC RRC RRC ANI 0FH ;'and' off the drive bits STA CUN ;save current user # MOV B,A ; IF USEMAX and nzcpr LDA USRMAX DCR A ENDIF ;USEMAX and nzcpr ; IF USEMAX and not nzcpr LD"  A USRMAX ENDIF ;USEMAX and not nzcpr ; IF NOT USEMAX MVI A,MAXUSR ENDIF ;NOT USEMAX ; CMP B JC OUTSIDE XRA A STA CTU ;set current try user to 0: STA ORIGCTU ;set original 'CTU' to same ; IF USEMAX and nzcpr LDA USRMAX ORTED ++',0 JMP DONE1 ;..... ; ; NOPRESS:LXI D,FCB MVI C,SRCHFST CALL BDOS ;check for directory match with 'FCB' CPI 0FFH ;a-reg. has 0-3 if file found else 0FFH JZ NXT ;do next drive if no more matches found CALL SHOFIL ;if match found DCR A ENDIF ;USEMAX and nzcpr ; IF USEMAX and not nzcpr LDA USRMAX ENDIF ;USEMAX and not nzcpr ; IF NOT USEMAX MVI A,MAXUSR ENDIF ;NOT USEMAX ; STA MAXTEMP ;set maximum user number to 'maxusr' ; SBOOT: LXI D,TBUF MVI C, display the filename ; SNEXT: ; ; lda flag cpi 00 jz avail2 ; MVI C,SRCHNXT CALL BDOS ;check for next match with FCB CPI 0FFH JZ NXT ;no more matches? then do next drive CALL SHOFIL ;if match found, display the filename JMP SN,SETDMA CALL BDOS ;set DMA address MVI A,0 ;start looking on 0 drive ('A') STA TRYDRV ;set up to try drive '0' first ; TRY: ; LDA TRYDRV ;try to select drive MOV E,A MVI C,SELDRV CALL BDOS LDA TRYDRV INR A STA TRYDRV ;get readyEXT ;continue until no more matches found ; NXT: ; LDA CTU ;increment current try user number INR A STA CTU MOV B,A LDA MAXTEMP CMP B JNC NXTUSR ;do next user number if all not done ; LDA ORIGCTU ;else reset user # and do next driv for next drive, too STA FCB ;store 1+drive# in FCB (1=A, 2=B, etc.) ; NXTUSR: ; LDA CTU ;set user to 'CTU' via a BDOS call MOV E,A MVI C,SETUSR CALL BDOS ; AVAIL: MVI C,CONSTAT ;check to see if key pressed CALL BDOS ORA A JZ NOPRESe STA CTU ; MVI C,RTNVER CALL BDOS ;see if CP/M version 1.4 or 2.x MVI C,5 ;(if CP/M 1.4, then BIOS must return an ORA A ;error if bad drive #, else won't work) JZ FOUR ;if 1.4 then four drives maximum ; IF NOT USEMAX ;if no trap then S ;if no key pressed, then continue MVI C,CONIN ;if key pressed, then check for abort CALL BDOS CPI 'X'-40H ;is it CTL-x? ; AVAIL1: JNZ NOPRESS ;if no, then continue avail2: CALL ILPRT ;if yes, then print abort message DB CR,LF,CR,LF,'++ ABthe maximum drive is MVI C,MAXDRV ; set manually. ENDIF ;NOT USEMAX ; IF USEMAX LDA DRIVMAX INR A MOV C,A ENDIF ;USEMAX ; FOUR: LDA TRYDRV CMP C JC TRY ;continue until all drives checked... ; ; ; ; ALL DONE NOW, RETURN #  TO CP/M ; DONE: LDA MFLAG ;see if any files found ORA A JNZ DONE1 ;if yes, then done, so exit CALL ILPRT ;if no, then say none found first DB CR,LF,CR,LF,'++ FILE NOT FOUND ++',0 ; DONE1: CALL ILPRT DB CR,LF,0 ;turn up a line LDA UDNUs at DMA address DAD H ;('A' register has relative position of DAD H ;name within directory record) DAD H DAD H DAD H ;multiply 'A' by 32 to point to start of LXI D,TBUF ;filename DAD D ;now point to filename XCHG ;save filename poiM ;restore user/drive number STA 4 ANI 0FH MOV E,A ;select the default drive MVI C,SELDRV CALL BDOS ; EXIT: LDA UDNUM RLC RLC RLC RLC ;make it a user area ANI 15 ;make it between 0 and 15 MOV E,A ;put it in 'E' register MVI nter in 'DE' ; IF NOT SHOWSYS ;then ignore 'SYS' files LXI H,10 DAD D ;point to 'SYS' file attribute MOV A,M ANI 80H ;check for 'SYS' type file RNZ ;don't display if 'SYS' attribute is set ENDIF ;NOT SHOWSYS ; LDAX D ;get user nuC,SETUSR ;set user area CALL BDOS ; EXITSPCL: LHLD STACK ;get old stack value SPHL RET ;all done ;..... ; ; NONAME: CALL ILPRT ;else, print help message and exit DB CR,LF DB ' You must specify the file(s) you',CR,LF DB ' wanmber INX D PUSH PSW ;save the user number CPI 9+1 ;is user number = 0 thru 9? JNC SHOFIL1 ;if not, exit MVI A,' ' CALL AOUT ;print the extra space ; SHOFIL1:LDA TRYDRV ;get the disk drive ADI 'A'-1 ;convert binary to ASCII CALL AOUTt to find. Wildcards are OK.',CR,LF,LF DB ' Example: FILE MODEM7.DOC',CR,LF DB ' FILE MOD*.*',CR,LF DB ' FILE *.ASM',CR,LF DB ' FILE *.*',CR,LF,0 JMP EXIT ;return to CP/M ; OUTSIDE:LDA CUN STA  ;display drive (a-p) POP PSW ;save the user number CPI 9+1 ;0-9 ? JC USRL ;if yes, exit ; SUI 10 ;user number = 10 thru 15 PUSH PSW ;remainder is <10 MVI A,'1' CALL AOUT2 ;print a leading '1' POP PSW ;get the remainder back ; USCTU ;set current try user to current user # STA ORIGCTU ;set original 'CTU' to same STA MAXTEMP ;set maximum user number to current JMP SBOOT ;and continue... ; SHOFIL: MOV L,A ;get filename to display from directory MVI H,0 ;which CP/M putRL: ADI '0' ;convert from binary to ASCII # CALL AOUT2 ;print digit ; NOUSR: MVI A,':' ;fence character CALL AOUT2 ;display a ':' to look nice MVI B,8 ;(8 characters or less in filename) ; PFN: LDAX D ;now print the filename.. INX D CAL$  L AOUT2 ;..one character at a time DCR B JNZ PFN ;continue for all 8 characters MVI A,'.' CALL AOUT2 ;display the '.' before the filetype MVI B,3 ;now do the same for the filetype ; PXT: LDAX D INX D CALL AOUT2 DCR B JNZ PXT LDA Ca a noteos sta lincnt typeret: POP H POP D POP B ;restore the registers RET ; cinput: MVI C,CONSTAT ;check to see if key pressed CALL BDOS ORA A JZ cinput ;if no key pressed, then continue MVI C,CONIN ;if key pressed, then check foOLUMN ;print MAXCOL columns across the screen DCR A JZ DOCRLF STA COLUMN CALL TWOSPC ;print two spaces to make it neat MVI A,0FFH ;show that a file was found STA MFLAG ;suppresses 'not found' message RET ;..... ; ; DOCRLF: MVI A,MAXCOr abort CALL BDOS cpi 'X'-40h jnz cinput1 xra a sta flag cinput1: ret ;..... ; ;..... ; ; INLINE PRINT ROUTINE ; ILPRT: XTHL ;set 'HL' to point to message ; ILPLP: MOV A,M ;get a character from message CALL AOUT2 ;output it L ;reset column number after last column STA COLUMN MVI A,CR CALL AOUT2 MVI A,LF CALL AOUT2 RET ;..... ; ; TWOSPC: MVI A,' ' CALL AOUT2 MVI A,' ' JMP AOUT2 ; AOUT: MOV B,A ;save the character for now LDA FIRST ORA A JNZ AOUT1 INX H ;point to next character MOV A,M ;check for end of message ORA A ;(00H marks end of message) JNZ ILPLP XTHL ;get proper return address onto stack RET ;then return to program ;..... ; ; COLUMN: DB MAXCOL ;column counter CTU: D CALL ILPRT DB CR,LF,CR,LF,0 MVI A,1 STA FIRST ; AOUT1: MOV A,B ; AOUT2: PUSH B ;send a character to the console PUSH D PUSH H ;save registers in case bdos eats them push psw ANI 7FH ;strip parity bit MOV E,A MVI C,2 CALL BDOS B 0 ;current try user number CUN: DB 0 ;currently logged-in user number FIRST: DB 0 ;first time use of 'AOUT' (for CR/LF) MAXTEMP:DB 0 ;maximum try user number MFLAG: DB 0 ;flag set to non-zero if file is found ORIGCTU:DB 0 ;original current try ;print the char. in 'A' on the console pop psw ani 7fh cpi lf jnz typeret lda lincnt inr a lxi h,mlps cmp m jc noteos lxi d,eosmsg mvi c,prints call bdos call cinput push d lxi d,cleosm mvi c,prints call bdos pop d xr user number TRYDRV: DB 0 ;number of drive being tried UDNUM: DB 0 ;user/drive number is saved here lincnt: db 0 mlps: db 22 flag: db 0ffh eosmsg: db ' [More]',cr,'$' cleosm: db ' ',cr,lf,'$' ; ;..... ; ; DS 64 ;32 level stack sho%  uld be enough room STACK: DS 2 ;..... ; ; END sm: db ' ',cr,lf,'$' ; ;..... ; ; DS 64 ;32 level stack sho22 flag: db 0ffh eosmsg: db ' [More]',cr,'$' cleosm: db ' ',cr,lf,'$' ; ;..... ; ; DS 64 ;32 level stack shoows files to be transferred to and from the system while in CP/M. Because the setup of these files is quite different for each system (due to available user areas, disk sizes and numbers, etc) I haven't assembled them. They will all assemble with ASM, so you shouldn't have any problems! These are all known working versions just as is, so go ahead and try out your own options! OZFILE will let you search the entire system for any files you specify on the command line. It looks for the maxdrive and maxuser bytes to provide system security. Thanks to Roy Robinson for this version.mand line. It looks for the maxdriions! OZFILE will let you search the entire system for any files you specify on the command line. It looks for the maxdri --> FILE: -FOG/HAK.022 CRC = 00 00 --> FILE: /HAK#022.DOC CRC = 92 23 --> FILE: BYE3-OS .ASM CRC = D6 1A --> FILE: OZFILE52.ASM CRC = CE 60 ---------------------> SUM OF CRCS = 36 9D &  '