ARTICLE TXT7APBYE69 ASM APBYE69 ASM !"#$%&'(APBYE69 ASM)*+,APMBOOT ASM<-./01234APMODEM DOC$56789APMODM22ASM:;<=>?@ABCDEFGHIAPMODM22ASMJKLMNOPQRSTUVWXYth consol (TTY:) th pape tap punc (PTP:) th use define punc # (UP1:) an th use define punc # (UP2:) Th RDR devic ca b b designate a th pape tap reade (PTR:) use define reade # (UR1:) an use define reade # nters modems an directl wit othe computers Fo instance i printe i connecte t th car i slo th comman PI PUN:=B:SAMPLE.DO wil prin th fil SAMPLE.DO foun i driv B:. PUN i a outpu device an RDR i a inpu devices. 2 O compute 1 ente PI PUN:=C:HERE.TXT Thi comman tell th compute tha i i t transfe th fil HERE.TX foun i driv C t the PUN: device. The PUN: device then sends the file to computer 2. Usin th APMODM22ASM9Z[\]^_`aCHAT COMbTAG ASM'cdefgXMODEM COMhiXMODEM DOC'jklmn named HERE.TX fro compute t compute 2 Th Appl seria por woul b seria o communication car i slo 2. The command sequence is the following: 1 On computer 2, ente PI B:THERE.DOC=RDR Thi comman tell th computevice Th abov exampl illustrate th outpu function W wil no examin metho fo usin bot th inpu an outpu funtions Let' assum tha w hav connecte tw computer throug thei seria I/ port ,an tha w wis t transfe fil abov approac i i possibl t transfe CP/ compatibl file between an Apple and any other CP/M based computer. Jus a wit th LST devic th logica PUN an RDR device hav physica devic options Th PUN devic ca b designate a Tw device infrequentl use b Appl CP/ user ar th punc (PUN: an reade (RDR:) Thes ar th logica devic name give t th I/ car i slo 2 PUN an RDR ca b use t communicat wit al sort o physica device suc a pri tha i i t receiv fil fro th RDR devic an t plac i i fil name THERE.DO i driv B: Not tha PI transfer file betwee logica device an tha th dis drive ar considere b CP/ to be a logical de (UR2:) Th name fo thes device ar thro back t th day o th Teletyp punc an reader Softcar CP/ version 2.20 an 2.2 hav th physica device UP1 identica t UP2 an UR1 identica t UR2: W ma selec whic physica devic followin byte t eliminat th scree clearin o war boot: (a) 0DF4H from A6H to 00H. (b) 24D8H from CDH to 00H. (c) 24D9H from A2H to 00H. (d) 24DAH from DAH to 00H. 4.Warm boot out of DDT and enter SAV devic chose fro I/ vecto tabl (F38AH,F38B fo PTR: F38CH,F38D fo UR1 an UR2:) A befor th tw I/ vector poin t th sam location whic ar DD59 fo 56 an FE6F fo 60K Th slo numbe i loade int th D register an table Th PUN vecto i a DA12 fo th 56 CP/ an a FA12 fo th 60 CP/M W ar no vectore t routin DB7B fo 56K FB7F fo 60K whic check th IOBYT fo th physica devic (th defaul devic i PTP:) Th devic i establish bu bu adde bu t RDR thi bu i complicate an result i gettin nothin yo aske for Fortunatel bot version ar eas t fix. Firs mak cop o you CP/ maste diskette an us th cop t perfor th followin operation evic i calle i analagou t th pat o th PUN device Th difference ar tha th characte t b rea wil b returne i th register Th characte i ASCI wit th parit bi cleare an th en o fil i t b marke b 1A (control-th logica devic use b changin th IOBYT a locatio 0003H Thi i mos easil accomplishe wit th STA command Fo example enterin STA PUN:=UP1 select th physica devic t b UP1:. W wil no trac th path take whe th PUN Input Routine Addresses 56K 60K Communications card DD26H FE4BH Serial card DD30H FDC1H Firmware card N/A FDB7H Befor yo ge carrie awa an star usinjum t th appropriat inpu routin follows Th latte jum wa deteremine durin th col boot A befor thes routine ca b modifie t sui you needs Th followin tabl list th RDR inpu routin location fo th variou car types. e an th outpu vecto i loade fro th I/ vecto tabl (F38EH,F38F i PTP o F390H,F391 i UP1 o UP2: an a indirec jum i mad t th outpu routine Th tw I/ vector poin t th sam outpu routine Th defaul outpu routin iwit DDT: 56K version 1.Load CPM56.COM into memory. 2.Change the byte at location 2581H from 20H to 28H. 3.I yo hav th Appl // wit a 8 colum car i th auxilliar slo yo ca chang th Z) Th RDR vecto i th eigt vecto i th BIO vecto jum tabl foun a DA15 fo 56 CP/ an a FA15 fo 60 CP/M Thi vecto point t th routin (DB8D fo 56K FB91 fo 60K whic check th IOBYT an jump t th appropriat physica an RDR device ar called Firs conside th PUN device T outpu characte throug PUN firs plac th th ASCI characte wit th parit bi cleare i th Z-8 registe an jum t th sevent jum instructio i th BIO jum vecto th PUN an RDR devices bette poin ou th bug whic ar i th 2.20 an 2.2 version o CP/M Th 2.20 versio ha th PTP an UP1 device exchanged I yo as fo PTP yo actuall ge UP1 an vic versa Th 2.2 versio fixe thiive routin location ar identica t thos fo th LST device Pleas refe t m previou articl fo thei locations Custo driver ca b installe i way identica t thos give i tha article. Tracin th pat take whe th RDR d a DD53 fo th 56 CP/ an a FE69 fo th 60 CP/M Th outpu routin firs load 0002 (th slo number int th D register an the jump t th appropriat drive routine Th drive routin wa selecte durin th col boot Th PUN drE 42 CPM56.COM. 5.Ente CPM5 an updat th diskett t th correcte master Th res o you ca b update b copyin th system track fro you ne maste with COPY.COM. 60K version 1.Loaduggested by Keith Petersen. ; This should make the program more portable. Also ; added Bruce Ratoff's update to DCHBYE program (5.5), ; that allows the use of bye from non-zero user areas. ; By Ron Fowler ; ;09/19/80 Modified COM file load rCorrected 3/18/81 null fix. Added ; additional description to heading of this file. (KBP) ; ;03/18/81 Add first-ring debounce routine, change PMMI HANGUP ; to do break for faster disconnect, fix error in P3TODTR ; equate for PMMI, added end-of me as for 56K version. Thi complete th CP/ devic discussions Nex tim wil discus th worl o th CP/ modem.copy logic to ; work through the BIOS printer driver. ; ;01/22/81 Changed carrier detect routine for DC Hayes to wait for ; 15 seconds after loss of carrier to return. ; ; if present. ; ; ;09/23/80program to relocate itself without using DDT to initially ;set it up. ; ;Modifications/fixes: (in reverse order to minimize reading time) ; ;03/30/81 COMBINED APBYE12 WITH ;MODIFIED VERSION OF BYE69. ; ;THANKS TO GORDON BANKS FOR THE ;ADDITION OF CPM60.COM into memory. 2.Change the byte at location 2897H from 008H to 04H. 3.Th Appl // auxillar slo 8 colum car correctio byt correction follow: (a) 0EF4 from A6H to 00H. (b) 27C4 from CDH to 00H. y log. (Formfeed seems to be a common "hit"). ; Changed local startup test to directly test for carrier ; instead of calling CARCK, to avoid 15 second delay. ; ; ; Rearranged patch list to "most recent first" order. ; Added mes-program error message to ; mark ending address (see note at label DEST). By KBP. ; Fix bug that prevented nulls at end of line if DUAL$IO ; was true. By Hank Szyszka. ; ; ;02/17/81 Added check for extraneous control characters in ; hardcop; APBYE V6.9 (revised 3/30/81) ; REMOTE CONSOLE PROGRAM FOR CP/M AND MODEM ; ;This program allows modem callers to use your CP/M system ;just as if they were seated at the system console. Special ;assembly-time options allow limiting the caller's ac Fixed bugs that prevented "bye /a" and "bye /c" from ; working properly. Also repaired several errors in ; conditional assembly nesting. By Ron Fowler ; ;09/20/80 Modified status checking during ring-wait routine to ; use cp/m BDOS call, as s'HIMEM' ROUTINES ;TO PREVENT TRANSIENT PROGRAMS ;FROM OVERWRITING BYE BY CHANGING ;THE JUMP VECTOR IN 6,7 TO BDOS ;TO ALLOW JUMPING AROUND THE ;PROGRAM. ; ;03/20/81 Fixed MOUTPUT so parity bit is stripped before outputting ; character to modem. (c) 27C5 from 82H to 00H (d) 27C6 from DAH to 00H. 4.Warm boot out of DDT and enter SAVE 44 CPM60.COM. 5.Same as for 56K version. Thi complete th CP/ devic discussions Nex tim wil discus th worl o th CP/ modem.sage for invalid-drive test. ; Added ANI 7Fh to upper case conversion test so that ; it's not fooled by bit 7 being set. ; Added WELUSR equate for user # containing WELCOME file. ; Removed PTRPORT equate and changed hard1 ; ; ;PLEASE NOTIFY ME OF ANY MOD- ;IFICATIONS: ; ; DAVID MORITZ ; 2228 N. SAWYER ; CGO.,IL. 60647 ; ; 312 384-4762 ; (24 HR. MODEM) ; ;Thanks to Bill Precht for the "label + offset" idea allowing ;this cess by ;password and/or access to only a message-service program. ; ;Based on an original program written by Dave Jaffe, January 1979 ;Rewritten for PMMI modem by Ward Christensen, February 1979. ; ;MODIFIED FOR DCH MMII ;BY DAVID MORITZ, MARCH 198outine to prevent BDOS ; overwrite if the COM file won't fit in the TPA ; By Ron Fowler ; ;09/19/80 Added new '/' option C, which has the same affect as ; /A, except that /C loads the com file after answering ; the phone, while /A boots cp/m.gram may patch itself in. ;Approximate memory requirements: 2k bytes or more, ;depending upon the options selected. A marker has ;been placed at the end to deliberately print an error ;message during assembly in order to determine the actual ;ending ck feature. Increased stack space to 60. ; By Keith Petersen. ; ;09/24/79 Added routines to allow automatic multiple baud ; rate selection, exit to CP/M from local console, ; echo nr. of nulls selected. By Keith Petersen, ; with thanks to Boset the DMA address back ; to 80h after the com file is loaded. By Ron Fowler ; ;09/16/80 Added conditional assembly to allow automatic ; loading of a com file instead of cp/m boot. Also ; added decimal usrlog counters as conditional ; assemget it right. ; 8. When password entered, if used, ; drops into CP/M. ; 9. Caller can leave by hanging up, ; (any time carrier is lost, it ; waits 15 seconds, then goes ; back to step 1), or the caller ; may type the program name (BYE) ; ;---; user log routines, and routines to print USRLOG ; information on console after program exit. ; By Dave Hardy ; ;07/10/80 Added code to allow auto-answer after first ; or second ring for more reliable auto-answer ; when using "ringback" op By Ron Fowler ; ;09/19/80 Added conditional assembly to give the operator a ; 'twit' logout key. Added conditionals for 'message ; from operator' and 'system down in 5 minutes' keys. ; Added front-panel selection of hard-copy log, remote ; runs up in high RAM. It gets there ;by being moved there when 'BYE' is typed. ; ;The program in high RAM 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 (sb Mathias for suggestions. ; ;05/06/79 Added routine to allow "callback" operation so modem ; does not answer normal voice calls. By Robbin Hough ; and Keith Petersen, W8SDZ. ; ;------------------------------------------------ ; ;This program bly. By Ron Fowler ; ;09/15/80 Added conditional assembly for automatic timed ; log-out, drive and user number masking, lower ; case query at login, and cp/m 2.x. Thanks to ; Bruce Ratoff for the routines (lifted from his ; 'DCHBYE54.ASM') --------------------------------------------- ; ;System equates ; FALSE EQU 0 TRUE EQU NOT FALSE CR EQU 0DH LF EQU 0AH MINUTES EQU 20*60 ;CONSTANT FOR 1 MIN TIME DELAY ; ;Change the following equate to an area in your ;high memory where this protion. By Dave Hardy ; ;06/29/80 Added USRLOG routines to keep track of number ; OF CALLERS. ; By Dave Hardy ; ; ;01/24/80 Added routines to preserve registers when calling ; the user's CBIOS. Added conditional assembly for ; callba'black-out', and password option. Also, if cpm/2 is ; used, a message is printed when an unsupported user ; area is entered. By Ron Fowler and Dave Hardy ; ;09/19/80 Modified to prevent re-load of the com file when ; a voice call comes in. Reee callback routines) ; 4. Awaits incoming carrier going to step 1 ; if none found in 15 seconds ; 5. Asks number of nulls (0-9) ; 6. Types the file "WELCOME" from ; disk, allowing CTL-C to skip it ; 7. Asks for a password, allowing ; 5 tried to off's overrun/framing error checking when read- ; ing the modem port. By Ron Fowler ; ;07/16/80 Added "/R" command option to allow USRLOG ; counters to be reset upon entry. By Dave Hardy ; ;07/11/80 Added conditional assembly for password and used to implement these functions ; NOTE: in order to implement the timed log-out, it ; was necessary to do timing in software loops. ; Therefore, a new equate, FASTCLK, has been added ; to allow for 4mhz clock speeds. Also added Bruce ; Rataddress of the program. The error message will ;not affect the assembly. Make sure you have memory ;available up to the address shown. ; DEST EQU 0BD00H ;RUNNING LOCATION OF CODE RSET EQU 0DAF0H ;WHERE CP/MLOADS THE BDOS ADDRESS JUMP EQUO ORA C JNZ MVLP ;IF NOT, DO SOME MORE ; PUSH H ;SAVE FOR LATER JUMP MVI A,0C3H ;CLEAR ANY TRAPS SO SYSOP.. STA 0 ;CAN USER "BYE /A" XRA A ;NEXT WARMBOOT TO USR0/DRV A STA 4 MVI C,14 ;MAKE DRIVE A DEFAULT MOV E,A ;LOG-IN DRIVE CP/M FUNCT STOP BITS P0EI EQU 20H ;ENABLE INTERRUPTS P0NORM EQU 15H ;NORMAL 8 BITS, NO PARITY P0110 EQU 11H ;SAME W/2 STOP BITS ; ;Modem status, input on RPORT (port 3) ; P2RDET EQU 80H ;RING DETECT P2CTS EQU 04H ;CTS (CARRIER DETEATURE? PWRQD EQU FALSE ;WANT TO USE PASSWORD? USRLOG EQU TRUE ;WANT TO COUNT NUMBER OF USERS? HARDLOG EQU FALSE ;WANT TO ECHO REMOTE KBD TO PRINTER? CPM2 EQU TRUE ;USING CP/M 2.x? MAXUSR EQU 3 ;SET TO 0 FOR CP/M 1.4 MAXDRV EQU 2 ;HIGHEST DRIVE SUPPOI A,JUMP ;WRITE A JMP OP-CODE IN FRONT OF THAT STA DEST-3 LXI H,DEST-3 ;MOVE THE NEW JUMP-TO ADDRESS.. SHLD RSET+1 ;..TO THE RESET VECTOR SETTER SHLD BDOS+1 ;AND TO BDOS JUMP ADDRESS MOVEUP LXI B,PE** ;* End of option configuration section * ;**************************************************** ; ; ; ;MMII MODEM ADDRESS EQUATES ; TPORT EQU 0E0A6H ;CONTROL/STATUS PORT DPORT EQU 0E0A7H ;DATA PORT RPORT EQU 0E0A5H ;RATE GEN/MODEM ST 0C3H ;OP-CODE FOR A JMP ; CONDATA EQU 0E000H ; ; ;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'. ; ;********************** ; ; ; ; ;--------------------------------------------------------- ; ORG 100H ; ;Move modem interface program up to high RAM and jump to it ; ;BUT FIRST, PROTECT BYE BY RESETTING BDOS JUMPS ; HIMEM LDA BDOS+2 ;HAS HIMEM ALREADY BEEN SECT) ; ;MMII modem status masks ; P0TBMT EQU 2 ;XMIT BUFF EMPTY P0DAV EQU 1 ;DATA AVAILABLE P0RPE EQU 40H ;REC'D PARITY ERR P0ORUN EQU 20H ;OVERRUN P0FERR EQU 10H ;FRAMING ERROR ; ;Baud rate divisors ; B110 EQU 0 ;110 BAUD B300 EQU 1 ;300 BAUDRTED FASTCLK EQU FALSE ;SET TRUE FOR 4 MHZ CLOCK TIMEOUT EQU TRUE ;WANT AUTO LOG-OFF FOR SLEEPY CALLERS? TOVALUE EQU 3 ;THIS IS 3 MINUTES TO AUTO LOGOUT WELUSR EQU 0 ;USER # THAT WELCOME FILE IS KEPT IN COMFILE EQU FALSE ;WANT TO AUTOBOOT A COM FILE? ND-START+1 ;NUMBER OF BYTES TO MOVE LXI H,DEST+PEND-START+1 ;END OF MOVED CODE LXI D,SOURCE+PEND-START ;END OF SOURCE CODE ; MVLP LDAX D ;GET BYTE DCX H ;BUMP POINTERS MOV M,A ;NEW HOME DCX D DCX B ;BUMP BYTE COUNT MOV A,B ;CHECK IF ZERATUS CPORT EQU 0E0A5H ;MODEM CONTROL RPORT1 EQU 0E0A6H ;STATUS ; ;Switch hook and modem commands, output to TPORT (port 0) ; P0BYE EQU 0 ;ON HOOK, OR DIALING BREAK P0ORIG EQU 8EH ;OFF HOOK, ORIG. P0ANSW EQU 8AH ;ANSWER PHONE P0TSB EQU 08H ;2****************************** ;* Option configuration section * ;**************************************************** ; PRINTER EQU TRUE ;WANT TO RETAIN LIST DEVICE? DUAL$IO EQU TRUE ;WANT CONSOLE & MODEM? CALLBAK EQU FALSE ;WANT CALLBACK FET? CPI 0CCH ;THIS IS WHAT IS NORMALLY THERE JZ CONT ;STILL CC, SO CONTINUE JMP MOVEUP ;ELSE SKIP NEXT BIT CONT LHLD BDOS+1 ;LOAD CURRENT BDOS JUMP SHLD DEST-2 ;PUT IN FRONT OF BYE MVhe following control codes (if used): ; TWITKEY EQU 'N'-40H ;KEYCODE TO LOG-OUT A CREEP MSGKEY EQU 'Q'-40H ;KEYCODE TO PRINT 'MESG FROM OPER:' SYSDKEY EQU 'O'-40H ;KEYCODE TO PRINT SYS DOWN MSG ; ; ;************************************************** COMUSR EQU 7 ;USER # THAT COMFILE IS KEPT IN DECIMAL EQU TRUE ;WANT DECIMAL VALUES FOR LOGS? TRAPLC EQU TRUE ;WANT TO TRAP LOWER CASE? ; ;Special keys for special functions ; FKEYS EQU TRUE ;WANT SPECIAL FUNCTION KEYS? ; ;Assign function keys to tION CALL BDOS ; IF CPM2 ;SET USER 0 MVI C,32 ;GET/SET USR CP/M FUNCTION MVI E,WELUSR CALL BDOS ENDIF ;CPM2 ; RET ;TO ADRS PUSHED ABOVE ; ; SOURCE EQU $ ;BOUNDARY MEMORY MARKER ; OFFSET EQU DEST-SOURCE ;RELOC AMOUNT ; ;-------------phone use by having computer ;folk 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 next 40 seconds. ; MVI L,45 ;NYTHING>" ; IF CPM2 AND COMFILE MVI C,32 ;GET/SET USER CODE MVI E,COMUSR ;LOCATION OF OUR COMFILE CALL BDOS ENDIF ;CPM2 AND COMFILE ; IF COMFILE CALL LODCOM ;LOAD THE COM FILE ENDIF ;COMFILE ; ; HANGUP2 EQU $+OFFSET ; ;Clear DTR OFFSET' will cause the pro- XX ;XX gram to JMP into whatever is currently XX ;XX in low memory, with unpredictable XX ;XX results. Be careful.... XX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ; ;If carrier lost, hang up, await ring. ;Otherisn't just relay bounce CALL DELAY ;.1 SEC DELAY FOR DEBOUNCE LDA RPORT ;GET STATUS ANI P2RDET ;STILL RINGING? JNZ RINGWT ;NO, IT WAS RELAY BOUNCE ; ;The phone is definitely ringing, now wait until ring is finished ; ENDRING EQU $+OFFSET CALL EQU $+OFFSET CALL CARCK ;SIGNED OFF W/THIS PROG? JC HANGUP ;NOBODY THERE ; GOODBY EQU $+OFFSET CALL ILPRT ;PRINT THIS MSG: DB CR,LF,'GOOD BYE, CALL AGAIN' DB CR,LF,CR,LF,0 CALL UNPATCH ;UNDO BIOS PATCHES ; ;Nobody there, or we are done, so----------------------------------; ; The following code gets moved ; ; to high RAM located at "DEST", ; ; where it is executed. ; ;-----------------------------------------------; ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XX C A U keyboard for CTL-C exit request. ;NOTE: Must do input via BDOS because CBIOS patches ;are not done until call comes in. LDA CONDATA ANI 7FH ;STRIP PARITY BIT CPI 'C'-40H ;CONTROL C? ; IF NOT USRLOG JZ 0 ;YES, --EXIT-- TO CP/M ENDcausing phone to hang up ; ; XRA A ;GET DISCONNECT VALUE STA TPORT ;RESET ORIG/ANSW STA CPORT ;TURN OFF DTR, DO BREAK ; ; ; MVI A,0C3H ;CLEAR ANY TRAPS.. STA 0 ;..LEFT FROM COM FILE ; ;Await ringing ; RINGWT EQU $+OFFSET ; ;Check localwise, say goodbye, and hang up ; START EQU $+OFFSET ; XRA A ;GET 0 STA LOSTFLG ;SHOW NO CARR. LOST ; ;Don't allow a remote user to do 'BYE /A' ; ; LDA RPORT1 ;AS ABOVE, FOR PMMI MODEM ANI P2CTS ;CD DEDUCED FROM CTS JZ GOODBY ; ; ;Check DELAY ;.1 SEC DELAY FOR DEBOUNCE LDA RPORT ;GET STATUS ANI P2RDET ;STILL RINGING? JZ ENDRING ;WAIT UNTIL RING FINISHED ; IF CALLBAK ;NEXT ROUTINES IMPLEMENT CALLBACK ; ;This routine minimizes the computer's interference ;with normal househole hang up ; HANGUP EQU $+OFFSET LXI SP,STACK ;SET UP LOCAL STACK XRA A ;FORCE NEXT WARMBOOT TO USER 0 STA 4 ;AND DRIVE A MVI C,14 ;MAKE DRIVE A DEFAULT MOV E,A CALL BDOS MVI A,' ' ;DON'T ALLOW OPTIONS.. STA OPTION ;..AFTER 1 "BYE / 0 MEANS "NO" JZ PASSINT ;NO WELCOME FILE ;Got a file, type it XRA A ;GET 0 STA FCBRNO ;ZERO RECORD # LXI H,100H ;GET INITIAL BUFF POINTER ; ;Type the welcome file WELTYLP EQU $+OFFSET CALL RDBYTE ;GETBITS RAR ;TO MAKE AN ASCII DIGIT RAR RAR CALL ONEOUT ;OUTPUT MSH TO CONSOLE MOV A,B ;GET NUMBER BACK ; ONEOUT EQU $+OFFSET ANI 0FH ;GET LSH FOR OUTPUT CPI 0AH ;CHECK IF ALPHA JC NOTAL2 ADI 07H ; NOTAL2 EQU $+OFFSET ADI 30H PUSH BE,1 ;..NO, SHOW MISS CPI CR ;C/R? JNZ PWMLP ;..NO, WAIT FOR C/R ; ;Password didn't match ; PWNMAT EQU $+OFFSET CALL ILPRT DB '++INCORRECT++',CR,LF,0 DCR D ;MORE TRIES? JNZ PASSINP ;YES JMP BADPASS ;NO, GO HANG UP ; ;Character matched inOUT GARBAGE ; PWMLP EQU $+OFFSET CALL MINPUT ;GET A CHAR CPI 'U'-40H ;CTL-U? JZ PASSINP ;YES, RE-GET IT CPI 60H ;LOWER CASE? JC NOTLC ;NO, ANI 5FH ;MAKE UPPER CASE ALPHA ; NOTLC EQU $+OFFSET CMP M ;MATCH PASSWORD? JZ PWMAT ;..YES MVI ;PRINT THIS MSG: DB CR,LF DB 'CAN YOUR TERMINAL DISPLAY LOWER CASE? ',0 MVI A,20H ;FORCE CASE CONVERSION FOR NOW STA ULCSW CALL MINPUT ;GET Y OR NO MOV C,A CALL MOUTPUT ;ECHO MOV A,C CPI 'N' JZ DONEOPT ;WE'RE ALREADY SET UP FOR NO LWR ; CALL ILPRT DB CR,LF,' ',0 ;PUT BOOT-UP MSG HERE ; IF COMFILE AND CPM2 MVI C,32 MVI E,COMUSR ;SWITCH TO COM FILE USER # CALL BDOS ENDIF ;COMFILE AND CPM2 ; IF COMFILE LDA OPTION CPI 'A' ;SYSOP CAN BYPASS COM FILE BY.. JZ 0 ;..TY A BYTE CPI 1AH ;EOF? JZ PASSINT ;YES, DONE MOV C,A ;SETUP FOR TYPE CALL MOUTPUT ;TYPE THE CHAR CALL MSTAT ;CHECK FOR.. ORA A ;CHAR TYPED? JZ WELTYLP ;..NO, LOOP CALL MINPUT ;..YES, GET CHAR CPI 'C'-40H ;CTL-C? JNZ WELTYLP ;..NO, LOOP U MVI C,02H MOV E,A ;OUTPUT THE NUMBER CALL BDOS POP B RET ENDIF ;USRLOG ; ;Welcome to the system ; WELCOME EQU $+OFFSET ; GETNULL EQU $+OFFSET CALL ILPRT ;PRINT THIS MSG: DB CR,LF DB 'HOW MANY NULLS (0-9) DO YOU NEED? ',0 CALL MI password ; PWMAT EQU $+OFFSET INX H ;TO NEXT CHAR CPI CR ;END? JNZ PWMLP ;..NO, LOOP ;End of password. Any missed chars? MOV A,E ;GET FLAG ORA A JNZ PWNMAT ;NOT RIGHT ;Password correct ENDIF ;PWRQD ; NOPASS EQU $+OFFSET ; IF USRLO B,13 ;LENGTH CALL MOVE ;MOVE THE NAME ;Set DMA address to 80h LXI D,80H MVI C,STDMA CALL BDOS ; IF CPM2 ;Set user number for welcome file MVI C,32 MVI E,WELUSR CALL BDOS ENDIF ;CPM2 ; ;Open the welcome file LXI D,FCB MVI C,OPENCASE CPI 'Y' JNZ GETULC ;WASN'T Y OR N...GO ASK AGAIN XRA A STA ULCSW ;SET FLAG FOR NO CONVERSION ; DONEOPT EQU $+OFFSET ENDIF ;TRAPLC ; CALL ILPRT DB CR,LF,0 ;Print the welcome file LXI H,WELFILN ;SOURCE LXI D,FCB ;DESTINATION MVI ENDIF ;NOT COMFILE ; ;TSTBAUD attempts to read a LF or CR, returns with ;zero flag if the character read is one of these two. ; TSTBAUD EQU $+OFFSET CALL MINPUT ;GET CHARACTER FROM MODEM CPI CR ;IF A CARRIAGE RETURN... RZ ;.. RETURN CPI LJMP TBL XRA A ;CLEAR OUT CARRIER.. STA LOSTFLG ;..LOST FLAG JMP HANGUP ; ;Readbyte routine - used to read the welcome file ; RDBYTE EQU $+OFFSET MOV A,H ;TIME TO READ? ORA A ;..IF AT 100H JZ NORD ;NO READ REQ'D ;Have to read a sector LXIXI B,4167 ENDIF ; JMP DELAY1 ; ;Patch in the new JMP table (saving the old) ; PATCH EQU $+OFFSET CALL TBLADDR ;CALC HL= CP/M JMP TABLE LXI D,VCOLDBT ;POINT TO SAVE LOCATION MVI B,18 ;ALWAYS SAVE PRINTER VECTOR CALL MOVE ;MOVE IT ;Now m POP D RET ; ;NOW TEST DRIVE #'S AND (IF CP/M 2.X) USER #'S TO ;insure that maximums are not exceeded. ; CARCK2 EQU $+OFFSET LDA 4 ;CHECK DISK/USER # ANI 0FH ;ISOLATE DRIVE CPI MAXDRV ;VALID DRIVE? JC CARCK3 ;YES, SKIP THIS JUIF MORE, DO IT RET ;IF NOT,RETURN ; ; ;Common routine to check for carrier lost, called from console out ; CHECK EQU $+OFFSET CALL CARCK ;SEE IF CARRIER STILL ON RNC ;ALL OK ; ;Carrier is lost. Type message so local console shows the reason JZ CARCK2 CALL DELAY DCR E JNZ CARCK5 STC POP D RET ; ;.1 sec delay routine ; DELAY EQU $+OFFSET PUSH B ; IF FASTCLK LXI B,16667 ;4 MHZ TIMING CONSTANT ENDIF ; F ;IF A LINEFEED... RET ;RET ZERO FLAG, ELSE NOT ZERO ; ;Loss of connection test ; CARCK0 EQU $+OFFSET;INITIAL PUSH D ;CARRIER MVI E,150 ;DETECT JMP CARCK5 ;ROUTINE CARCK EQU $+OFFSET PUS TABLE CALL MOVE ;MOVE ORIG BACK RET ; ;Calculate HL=CP/M's jump table, B=length ; TBLADDR EQU $+OFFSET LHLD 1 ;GET BIOS POINTER DCX H ;..SKIP DCX H ;..TO DCX H ;..COLD BOOT ; IF NOT PRINTER MVI B,18 ;BYTES TO MOVE ENDIF ; IF ove new JMP table to CP/M CALL TBLADDR ;CALC HL=CP/M'S JMP TABLE XCHG ;MOVE TO DE LXI H,NEWJTBL ;POINT TO NEW CALL MOVE ;MOVE IT RET ; UNPATCH EQU $+OFFSET CALL TBLADDR ;HL=CP/M'S JMP TABLE XCHG ;MOVE TO DE LXI H,VCOLDBT ;GET SAVEDNK LDA 4 ;GET WHOLE LOGIN BYTE ANI 0F0H ;RETAIN USER # & FORCE DRIVE TO A STA 4 ;UPDATE LOGIN BYTE CALL ILPRT ;TELL USER WHAT HE DID DB 'INVALID DRIVE - RETURNING TO A:',0 JMP 0 ;WARM BOOT ; CARCK3 EQU $+OFFSET ; IF CPM2 LDA 4 ;GET LOGIN ; BADPASS EQU $+OFFSET ;COME HERE ON BAD PASSWORD MVI A,1 ;SHOW CARRIER LOST SO STA LOSTFLG ;..WE WON'T CK AGAIN LXI SP,STACK ;ENSURE VALID STACK CALL ILPRT DB CR,LF DB '++CARRIER LOST++' DB CR,LF,' ',0 CALL UNPATCH ;RESTORE ORIG BIOS IF NOT FASTCLK LXI B,8334 ;2 MHZ TIMING CONSTANT ENDIF ; DELAY1 EQU $+OFFSET DCX B MOV A,B ORA C JNZ DELAY1 POP B RET ; ;50 ms delay routine ; KDELAY EQU $+OFFSET PUSH B ; IF FASTCLK LXI B,8334 ENDIF ; IF NOT FASTCLK LH D MVI E,150 CARCK1 EQU $+OFFSET LDA RPORT1 ANI P2CTS ;GOT A CARRIER? JZ CARCK2 ;YES, GO ON WITH TESTS CALL DELAY ;WAIT .1 SECONDS DCR E ;COUNT DOWN TIME JNZ CARCK1 STC PRINTER ;RETAIN LIST DEVICE? MVI B,15 ;DON'T MOVE LISTER JUMP ENDIF ; RET ; ;Move (HL) to (DE), length in (B) ; MOVE EQU $+OFFSET MOV A,M ;GET A BYTE STAX D ;PUT AT NEW HOME INX D ;BUMP POINTERS INX H DCR B ;DEC BYTE COUNT JNZ MOVE ;TURNING TO 0++',0 JMP 0 ;WARM BOOT ENDIF ;CPM2 ; CARCK4 EQU $+OFFSET ORA A POP D RET ; CARCK5 EQU $+OFFSET LDA DPORT LDA DPORT LDA RPORT1 LDA RPORT1 ANI P2CTS BYTE ANI 0F0H ;ISOLATE USER # CPI MAXUSR*16+1 ;VALID USER #? JC CARCK4 ;YES, DON'T CHANGE LDA 4 ;GET LOGIN BYTE AGAIN ANI 0FH ;KEEP DRIVE, ZERO USER STA 4 ;UPDATE LOGIN BYTE CALL ILPRT ;TELL HIM WHAT HAPPENED DB '++INVALID USER NUMBER - RE D,FCB MVI C,READ CALL BDOS ORA A ;OK? MVI A,1AH ;FAKE UP EOF RNZ ;RET EOF IF BAD LXI H,80H ; NORD EQU $+OFFSET MOV A,M ;GET CHAR INX H ;TO NEXT RET ; ;Keyboard/modem status test routine ; MSTAT EQU $+OFFSET ; IF DUAL$IO ;WANT LRE ;Access password (ends in carriage return) ; PASSWD EQU $+OFFSET DB 'HELLO' ;THE PASSWORD ITSELF DB CR ;END OF PASSWORD ;Allow room for bigger password to be patched in DB 0,0,0,0,0,0,0,0,0,0,0,0,0 ENDIF ;PWRQD ; ;Routine to load the COM SILENT ;AVOID LOOP IN CASE CARRIER LOST CALL CHECK ;CARRIER STILL ON? LDA TPORT ;GET MODEM STATUS ANI P0TBMT ;TRANSMIT BUFFER EMPTY? JZ MOUTPUT ;LOOP IF NOT READY MOV A,C ;GET CHAR ANI 7FH ;STRIP PARITY BIT IF TRAPLC CPI 60H ;CHECK FOR LOWEEOUT PUSH H LXI H,TOVALUE*MINUTES ;INITIALIZE TIMEOUT COUNTER SHLD TOCNT POP H ENDIF ;TIMEOUT ; MINPUT1 EQU $+OFFSET LDA LOSTFLG ;KNOWN LOSS.. ORA A ;..OF CARRIER? CZ CHECK ;CARRIER STILL ON? CALL MSTAT ;ANYTHING? ORA A ; IF NOT Tnect if JMP at 0 has been altered ; MBOOT EQU $+OFFSET LDA 0 ;LOOK AT OPCODE CPI 0C3H ;IS IT STILL JMP? JZ VWARMBT ;YES, ALLOW IT JMP NOSLASH ;NO, DISCONNECT ; ;Inline print routine ; ILPRT EQU $+OFFSET XTHL ;SAVE HL, GET MSG PUSH B ;SAVINEFEED MVI A,LF CALL LISTOUT ;SO SEND IT MVI A,CR ;GET BACK CR ENDIF ;END OF HARDLOG ; NOLOG EQU $+OFFSET ; CPI 3 ;IS IT CONTROL-C? RNZ ;NO, PASS IT THRU LDA 0 ;SEE IF WARM BOOT DISABLED CPI 0C3H ;JMP MEANS WARM BOOT OK MVI A,3 ;SO OCAL CONSOLE? CALL CONSTAT ;GET LOCAL STATUS ORA A RNZ ;RET IF LOCAL CHAR ENDIF ;DUAL$IO ; LDA TPORT ;GET STATUS ANI P0DAV ;DATA AVAILABLE? RZ ;RETURN IF NOT READY LDA TPORT ;GET STATUS ANI 30H ;CHECK FRAMING AND OVERRUN BITS JZ MST ; SILENT EQU $+OFFSET ; IF DUAL$IO ;TO LOCAL ALSO? PUSH PSW ;SAVE CHAR CALL CONOUT ;SEND TO REGULAR BIOS POP PSW ;GET CHAR AGAIN ENDIF ;DUAL$IO ; ;Check for nulls CPI LF ;TIME FOR NULLS? RNZ ;NO, RETURN ;Send nulls if required LDA R CASE JC MOUTP2 ;SKIP IF NOT LC CPI 7FH ;CHECK FOR RUBOUT JZ MOUTP2 PUSH H LXI H,ULCSW ;SUBTRACT EITHER 20H OR 0 SUB M POP H MOV C,A ;FORCE ON LOCAL AS WELL AS REMOTE ; MOUTP2 EQU $+OFFSET ENDIF ;TRAPLC ; STA DPORT ;OUTPUT TO MODEMIMEOUT JZ MINPUT ;LOOP TILL CHAR RCD ENDIF ;NOT TIMEOUT ; IF TIMEOUT JNZ MINPUT2 CALL KDELAY ;KILL 50 MS PUSH H LHLD TOCNT ;KNOCK DOWN TIMEOUT COUNTER DCX H SHLD TOCNT MOV A,H ORA L POP H JNZ MINPUT1 ;STILL TIME LEFT..KEEP TRYINE BC REGS ; ILPLP EQU $+OFFSET MOV C,M ;GET CHAR CALL MOUTPUT ;OUTPUT IT INX H ;POINT TO NEXT MOV A,M ;TEST ORA A ;..FOR END JNZ ILPLP POP B ;RESTORE BC REGS XTHL ;RESTORE HL, RET ADDR RET ;RET PAST MSG ; IF PWRQD ;KEEP PASSWORD HERETURN CONTROL-C RZ XRA A ;ELSE CONVERT TO NULL RET ; ;Modem output function ; MOUTPUT EQU $+OFFSET ; ;If we already know carrier is lost, don't check ;for it again or loop trying to output. LDA LOSTFLG ;KNOWN LOSS OF CARRIER? ORA A JNZ AT1 ;NO ERRORS...LEGIT CHARACTER LDA DPORT ;SWALLOW CHARACTER (CLEARS PODAV) SUB A ;RETURN FALSE RET MSTAT1 EQU $+OFFSET MVI A,0FFH ;SHOW READY ORA A RET ; ;Modem input function, checks local console first ; MINPUT EQU $+OFFSET ; IF TIMNULLS ;GET COUNT ORA A ;ANY? RZ ;..NO PUSH B MOV B,A ;SAVE COUNT MVI C,0 ;0 IS A NULL ; NULLP EQU $+OFFSET CALL MOUTPUT ;TYPE A NULL DCR B ;MORE? JNZ NULLP ;..YES, LOOP POP B MVI C,LF ;RESTORE LF RET ; ;Boot trap - becomes disconwasn't ready, so read modem ; LDA DPORT ;GET DATA BYTE ANI 7FH ;DELETE PARITY JZ MINPUT ;IGNORE NULLS IF HARDLOG CPI 20H JNC MINPUT3 CPI CR JNZ NOLOG ; MINPUT3 EQU $+OFFSET CALL LISTOUT ;ECHO ON PRINTER CPI CR JNZ NOLOG ;CR NEEDS LG CALL ILPRT DB '++INPUT TIMED OUT++',7,7,0 JMP NOSLASH ENDIF ;TIMEOUT ; MINPUT2 EQU $+OFFSET ; IF DUAL$IO ;BOTH LOCAL AND REMOTE CALL CONSTAT ;CHECK LOCAL CONSOLE ORA A ;CHAR? JNZ CONIN ;..YES, READ IT, RET. ENDIF ; ;Local console file ; IF COMFILE LODCOM EQU $+OFFSET XRA A ;INITIALIZE FCB STA COMFCB LXI H,COMFCB+12 MVI B,21 ; ZLOOP EQU $+OFFSET MVI M,0 INX H DCR B JNZ ZLOOP ; MVI C,OPEN ;NOW OPEN THE FILE LXI D,COMFCB CALL BDOS INR A ;SHOULD BE NON-ZE DS 3 ; VCONIN EQU $+OFFSET DS 3 ; VCONOUT EQU $+OFFSET DS 3 ; VLISTOUT EQU $+OFFSET DS 3 ; ;Since these areas are not initialized, ;the following counters will not be changed ;by subsequent loads of this program ; IF USRLOG OLDSYSDOWN ;TELL CALLER TO LEAVE CPI TWITKEY JZ GOODBY ;MAKE CALLER LEAVE CPI MSGKEY RNZ CALL ILPRT ;SEND CALLER A MESSAGE DB 'MESSAGE FROM OPERATOR:',0 MVI A,' ' ;SOMETHING TO RETURN WITH RET ; SYSDOWN EQU $+OFFSET CALL ILPRT DB 'SYSTEMFOR NEXT TIME MOV A,E ;SUBTRACT: (TOP) - (ADRS) SUB L MOV A,D ;ONLY THE CARRY NEEDED SBB H JNC SIZEOK ;CY= BETTER MOVCPM CALL ERRXIT ;SO TELL THE STORY DB '++PROGRAM AREA TOO SMALL++','$' ; SIZEOK EQU $+OFFSET INX B PUSH B PUSH H ;SAVICBBSCOM' ;COM file name ^^^^^^^^^^^ (must be 11 characters) ; PEND EQU $+OFFSET ;END OF RELOCATED CODE ; ;These areas are not initialized ; DS 21 ;REST OF COM FCB ; ULCSW EQU $+OFFSET DS 1 ; OPTION EQU $+OFFSET DS 1 ; TOCNT EQU $+OFFS MVI C,PRINTF CALL BDOS ;PRINT THE ABORT MSG JMP 0 ;WARM BOOT ENDIF ;COMFILE ; ;This area is used for vectoring calls to the ;user's CBIOS, but saving the registers first ;in case they are destroyed. ; CONSTAT EQU $+OFFSET PUSH B PUSH D RO JZ ABORT ;NO FILE, ABORT ; ;Now load the file LHLD 6 ;GET TOP OF MEMORY LXI D,-80H ;RECORD LOADS CAN'T START.. DAD D ;..ABOVE (BDOS) - 80H PUSH H ;SAVE ON STACK ; LXI D,80H ;TPA-80H LXI B,0 ;KEEP A RECORD COUNTER PUSH B ;SAVE COUNTER OP PSW POP H POP D POP B RET ; ;This is the JMP table which is copied on top ;of the one pointed to by location 1 in CP/M ; NEWJTBL EQU $+OFFSET JMP MBOOT ;COLD BOOT JMP MBOOT ;WARM BOOT JMP MSTAT ;MODEM STATUS TEST JMP MINPUT ;MODEM I DOWN IN' DB ' 5 MINUTES....',0 MVI A,' ' RET ENDIF ;FKEYS ; CONOUT EQU $+OFFSET PUSH B PUSH D PUSH H CALL VCONOUT POP H POP D POP B RET ; LISTOUT EQU $+OFFSET PUSH B PUSH D PUSH H PUSH PSW MOV C,A CALL VLISTOUT PE TPA ADRS XCHG ;ALIGN REGISTERS MVI C,STDMA ;TELL BDOS WHERE TO PUT RECORD CALL BDOS LXI D,COMFCB ;NOW READ THE RECORD 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 ;MOET DS 2 ; ;Byte to keep track of lost carrier when ;typing "++CARRIER LOST++" so we don't loop ; LOSTFLG EQU $+OFFSET DS 1 ; ;Save the CP/M jump table here ; VCOLDBT EQU $+OFFSET DS 3 ; VWARMBT EQU $+OFFSET DS 3 ; VCONSTAT EQU $+OFFSET PUSH H CALL VCONSTAT POP H POP D POP B RET ; CONIN EQU $+OFFSET PUSH B PUSH D PUSH H CALL VCONIN ; IF FKEYS CALL CKFUNC ENDIF ;FKEYS ; POP H POP D POP B RET ; CKFUNC EQU $+OFFSET ; ; IF FKEYS CPI SYSDKEY JZ PUSH D ;AND LOAD ADDRESS ; GLOOP EQU $+OFFSET POP D ;GET TPA ADRS LXI H,80H ;POINT TO NXT ADRS 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-OF-MEMORY) PUSH D ;RE-SAVE NPUT ROUTINE JMP MOUTPUT ;MODEM OUTPUT ROUTINE RET ;DUMMY LIST DEVICE NOP NOP ; WELFILN EQU $+OFFSET DB 0,'WELCOME ',0 ;Welcome file name ^^^^^^^^^^^ (must be 11 characters) ; NULLS EQU $+OFFSET DB 5 ; COMFCB EQU $+OFFSET DB 0,'MINSET POP D LDA OPTION ;SEE IF THIS WAS "BYE /C" CPI 'C' ;IF IT WAS THEN.. RZ ;..DON'T PRINT MESSAGE MVI C,PRINTF CALL BDOS RET ; ABORT EQU $+OFFSET CALL ERRXIT DB CR,LF DB '++CANNOT FIND COM FILE++','$' ; ERRXIT EQU $+OFFSET POP DRE 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 CALL LOADOK ;PRINT THIS MSG TO CONSOLE: DB '++COM FILE LOADED++',CR,LF,'$' ; LOADOK EQU $+OFFUSR EQU $+OFFSET DS 1 ; NEWUSR EQU $+OFFSET DS 1 ; NONUSR EQU $+OFFSET DS 1 ENDIF ;USRLOG ; ; DS 60 STACK EQU $+OFFSET ;LOCAL STACK ; ENDMARK EQU $+OFFSET ;! IGNORE ERROR. THIS MARKS END OF PGM ; ;BDOS equates ; CI EQU 1 WRCON EQU DRCVB EQU 1 MODRCVR EQU 1 MODDATP EQU 0E0A7H MODCTL2 EQU 0E0A5H ORIGMOD EQU 8FH ANSWMOD EQU 8AH ; ERRLIM EQU 10 ; SOH EQU 1 EOT EQU 4 ACK EQU 6 NAK EQU 15H CAN EQU 18H LF EQU 10 CR EQU 13 ; BDOS EQU BASE+5 FCB EQU BASE+5CH ; ORG BAve the ;'ESC' key and/or provision for control characters. ;See equates. ; ;HOW TO USE APBOOT.ASM: THE PROGRAM IS SHORT ENOUGH ;TO TYPE IN WITHIN A REASONABLE PERIOD OF TIME. ;ONCE INSTALLED AS A COM FILE, DIAL A REMOTE SYSTEM ;CONTAINING A COPY OF ed to make this file easier to transport from one ;system to another. (KBP) ; NOTE:IF TYPING IN PROG..BEGINHERE: ; FALSE EQU 0 TRUE EQU NOT FALSE ; ; BASE EQU 0 ; ; EXITCHR EQU 05H ;CTL-E TO EXIT TERM MODE TO CP/M ESC EQU 1BH ;ESCAPE TO he part of the host ;system's operator. ; ;COMMANDS: MBOOT FILENAME.FILETYPE ; or MBOOT A:FILENAME.FILETYPE ; or MBOOT B:FILENAME.FILETYPE ; ;The program will operate as a dumb terminal until ;an 'ESC' key is typed (ctrl-[). It then branches ;2 DRECTIO EQU 6 PRINTF EQU 9 CSTS EQU 11 OPEN EQU 15 READ EQU 20 STDMA EQU 26 BDOS EQU 5 FCB EQU 5CH FCBRNO EQU FCB+32 ; END OTE IS PROPERLY INITIATED TOSEND, TYPE AN ESC ;AND THE PROGRAM WILL BEGIN TO TRANSFER. THE TRANSFER ;IS 'QUIET' AND TAKES ABOUT 20 MIN (A GUESS) SO THE ;ONLY WAY YOU'LL KNOW THE PROGRAM WORKS IS BY WATCHING ;FOR THE DISK ACCESS LED TO COME ON AS THE APMODEM.ASM(ANY VERSION) AND ;WHEN THE CARIER IS HEARD TYPE: APMBOOT APMODEM.ASM (CR). ;THIS WILL TURN ON YOUR MMII IN ORIGINATE MODE AND ;ALLOW YOU YOU COMMUNICATE WITH THE REMOTE AS A TERMINAL. ;THEN TYPE:XMODEM S APMODEM.ASM AND A CR. WHEN THE ;REM; ; APMBOOT.ASM ver 3.0 ; (revised 5 Nov 80) ; ; MODIFIED FOR USE ON APPLE W/MMII BY DAVID MORITZ, 2/1/81 ; ;MODEM BOOT PROGRAM by Keith Petersen, W8SDZ. ;Thanks to John Taylor for idea of incorporating ;simple terminal routine. Based on MODEM.ASMEXIT TERM MODE TO FILE RCVE ; FASTCLK EQU FALSE ;TRUE FOR 4 MHZ CLOCK ; ; ;IF YOU ARE USING AN EXTERNAL MODEM (NOT S-100 PLUG-IN) ;CHANGE THESE EQUATES FOR YOUR MODEM PORT REQUIREMENTS ; ; ; ; MODCTLP EQU 0E0A6H MODSNDB EQU 2 MODSNDR EQU 2 MOto the receive routine. The user may also exit ;to CP/M without opening the receive file by typing ;ctrl-E from the terminal. The values for the escape ;and exit keys may be changed in accordance with the ;needs of the user - some keyboards do not haBUFFER IS ;DUMPED TO DISK EVERY 16 SECTORS. IF YOU HAVE ANY ;PROBLEMS OR QUESTIONS FEEL FREE TO CONTACT ME.: ; DAVID MORITZ ; 312 384-4762 ; (24HR MODEM) ; ;NOTE: Comments for the source code and tabs have been ;removPORTS ARE SET UP FOR ;DCH MMII: 'ORIGINATE' MODE, 300BAUD. ; ;A simple terminal routine at start of program allows ;user to communicate with a remote system prior to ;receiving a file to make it possible to down-load ;a file without intervention on t V2.0, ;by Ward Christensen with enhancements from MODEM527. ; ;CP/M - CP/M file transfer program (receive-only) ; ;This program is intended for use as a way to ;initially transfer APMODEM.COM or APMODEM.ASM to ;A NEW USER. ;ALL EQUATES, FLAGS AND SE+100H ; LXI H,0 DAD SP SHLD STACK LXI SP,STACK CALL INITADR CALL ILPRT DB 'APMBOOT as of ' DB '2/1/81',CR,LF,0 LDA FCB+1 CPI ' ' JNZ TERMI CALL ILPRT DB '++NO FILE NAME SPECIFIED++',CR,LF,0 JMP EXIT ; TERMI CALL INITMOD L CALL $-$ POP H POP D POP B POP PSW RET ; STAT PUSH B PUSH D PUSH H VSTAT CALL $-$ POP H POP D POP B ORA A RET ; KEYIN PUSH B PUSH D PUSH H VKEYIN CALL $-$ POP H POP D POP B ANI 7FH RET ; ILPRT XTHL ; ILPLP M ANI 5FH CPI 'Y' JNZ MXIT LXI D,FCB MVI C,19 JMP BDOS ; MAKEFIL LXI D,FCB MVI C,22 CALL BDOS INR A RNZ CALL ERXIT DB '++ERROR - CAN''T MAKE FILE',CR,LF DB '++DIRECTORY MUST BE FULL$' ; CLOSFIL LXI D,FCB MVI C,16 CALL BDOS CALL SENDACK JMP RCVLP ; RCVEOT CALL WRBLOCK CALL SENDACK CALL CLOSFIL CALL ERXIT DB CR,LF,'TRANSFER COMPLETE$' ; RCVSECT XRA A STA ERRCT ; RCVRPT MVI B,10 CALL RECV JC RCVSERR CPI SOH JZ RCVSOH ORA A JZ RCVRPT CPI EOT Z MSEC POP D STC RET ; MCHAR LDA MODDATP POP D PUSH PSW ADD C MOV C,A POP PSW ORA A RET ; INITADR LHLD BASE+1 LXI D,3 DAD D SHLD VSTAT+1 DAD D SHLD VKEYIN+1 DAD D SHLD VTYPE+1 RET ; INITMOD EQU $ ; ; ; MVI A,1LDA MODCTLP ; ANI MODSNDB CPI MODSNDR JNZ SENDW POP PSW STA MODDATP RET ; ABORT LXI SP,STACK ; ABORTL MVI B,1 CALL RECV JNC ABORTL MVI A,CAN CALL SEND ; ABORTW MVI B,1 CALL RECV JNC ABORTW MVI A,' ' CALL SEND CALL ERXITDA MODDATP LDA MODDATP CALL ILPRT DB CR,LF,'TERMINAL MODE',CR,LF DB 'CTL-E exits to CP/M, ESC starts file transfer' DB CR,LF,0 ; TERM CALL STAT JZ TERML CALL KEYIN CPI EXITCHR JZ EXIT CPI ESC JZ RCVFIL STA MODDATP ; ; TERML LDALP PUSH H PUSH D PUSH B MVI C,26 CALL BDOS LXI D,FCB MVI C,21 CALL BDOS POP B POP D POP H ORA A JNZ WRERR LXI H,80H DAD D XCHG DCR C JNZ DKWRLP XRA A STA SECINBF LXI H,DBUF SHLD SECPTR ; RSDMA LXI D,BASE+80H MV INR A RNZ CALL ERXIT DB '++CAN''T CLOSE FILE$' ; WRSECT LHLD SECPTR XCHG LXI H,BASE+80H CALL MOVE128 XCHG SHLD SECPTR LDA SECINBF INR A STA SECINBF CPI 16 RNZ ; WRBLOCK LDA SECINBF ORA A RZ MOV C,A LXI D,DBUF ; DKWR STC RZ ; RCVSERR MVI B,1 CALL RECV JNC RCVSERR MVI A,NAK CALL SEND LDA ERRCT INR A STA ERRCT CPI ERRLIM JC RCVRPT ; RCVSABT CALL CLOSFIL CALL ERXIT DB '++UNABLE TO RECEIVE BLOCK' DB CR,LF,'++ABORTING++$' ; RCVSOH MVI B,1 5H STA MODCTLP ; ; LXI H,4000 ; OFFDLY DCR L JNZ OFFDLY DCR H JNZ OFFDLY MVI A,ORIGMOD STA MODCTL2 ; RET ;<--THIS RET MUST BE HERE ; CRLF MVI A,CR CALL TYPE MVI A,LF ; TYPE PUSH PSW PUSH B PUSH D PUSH H MOV C,A VTYPE DB 'APMBOOT PROGRAM CANCELLED$' ; INCRSNO LDA SECTNO INR A STA SECTNO RET ; ERASFIL LXI D,FCB MVI C,17 CALL BDOS INR A RZ CALL ILPRT DB '++FILE EXISTS, TYPE Y TO ERASE: ',0 CALL KEYIN PUSH PSW CALL TYPE CALL CRLF POP PSW MODCTLP ; ANI MODRCVB CPI MODRCVR JNZ TERM LDA MODDATP ANI 7FH CALL TYPE JMP TERM ; RCVFIL CALL ERASFIL CALL MAKEFIL CALL ILPRT DB 'FILE OPEN, READY TO RECEIVE',CR,LF,0 ; RCVLP CALL RCVSECT JC RCVEOT CALL WRSECT CALL INCRSNOI C,26 JMP BDOS ; WRERR CALL RSDMA CALL ILPRT DB '++ERROR WRITING FILE',CR,LF,0 JMP ABORT ; RECV PUSH D ; ; MSEC LXI D,50000 ; ; MWTI LDA MODCTLP ; ANI MODRCVB CPI MODRCVR JZ MCHAR DCR E JNZ MWTI DCR D JNZ MWTI DCR B JNMVI B,1 CALL RECV JC RCVSERR CMP D JNZ RCVSERR LDA RCVSNO MOV B,A LDA SECTNO CMP B JZ RECVACK INR A CMP B JNZ ABORT RET ; RECVACK CALL SENDACK JMP RCVSECT ; SENDACK MVI A,ACK ; SEND PUSH PSW ADD C MOV C,A ; ; SENDW CALL RECV JC RCVSERR MOV D,A MVI B,1 CALL RECV JC RCVSERR CMA CMP D JZ RCVDATA JMP RCVSERR ; RCVDATA MOV A,D STA RCVSNO MVI C,0 LXI H,BASE+80H ; RCVCHR MVI B,1 CALL RECV JC RCVSERR MOV M,A INR L JNZ RCVCHR MOV D,C OV A,M ORA A JZ ILPRET CALL TYPE INX H JMP ILPLP ; ILPRET XTHL RET ; ERXIT POP D MVI C,9 CALL BDOS ; MXIT CALL ILPRT DB CR,LF,'DON''T FORGET TO DISCONNECT MODEM' DB CR,LF,0 ; EXIT LHLD STACK SPHL RET ; MOVE128 MVI B,128 ; and if carrier is detected, drops into terminal mode. If the carrier is not detected, it hangs up. T terminal mode. Full duplex. S send a file to another computer. R receive a file from another computer. E act as a computer (echo modem II. Version 2.0 implements auto- dialing feature of this modem, while version 1.0 does not. To make the COM file, simple type ASM APMODEM2 (of course, the assembler, ASM.COM must be on the disk) and then LOAD APMODEM2. If you have another a terminal in the originate mode. MODEM S.110 PIP.COM ==>sends the file PIP.COM to another computer at 110 baud. The commands can be classed as primary and secondary commands. The primary command is represented by the first letter of the et-up currently extant on the Apple. It has been tested with the D.C. Hayes Micromodem II, the CCS 7710A serial interface, and the Apple communications card. It should also work with the SSM serial board, but I have not tested it with this board or th MOVE MOV A,M STAX D INX H INX D DCR B JNZ MOVE RET ; RCVSNO DB 0 SECTNO DB 0 ERRCT DB 0 EOFLG DB 0 SECPTR DW DBUF SECINBF DB 0 DS 60 STACK DS 2 DBUF EQU $ ; END ired) to TRUE. The conditional assembly will then take place properly for you modem. The modem program is very simple to use and self documenting if you type MODEM H (for help). The program is controlled by the command line which alsmodem than the Micromodem, you must change the equate for the Micromodem (found in the first few program lines after the opening comments) to FALSE and the equate for your modem to TRUE. You must also change the equate for INITREQ (initialization requ APMODEM VERSION 2.0 AND VERSION 1.0 APMODEM is a modification of Ward Christensen's famous program MODEM which allows transfer of programs under the CP/M operating system. This program has been so popular, that it has established the protocol commands string. Allowable primary commands are: H prints the help file...a list of the commands. X examples of how to use the modem program. C (Micromodem II only) automatically dial a number. The program then asks for the number, dials it,e Apple serial interface. Should you find that it doesn't work with these, please let me know, or even better, fix the program so that it works! The program is supplied as an ASM file, and will assemble without modification to run with the Microo invokes the program. To use simply type (from CP/M): MODEM (command string). The command string consists of a series of characters specifying the function the modem is to carry out. For example: MODEM TO ==> sets the modem up as nsive amount of public domain software available. With this modified version of Ward's program, coupled with the many remote CP/M systems, all of this software is now available to Apple users. This program should work with just about any modem sfor CP/M file transfer via modem. Apple CP/M is a full 56k standard CP/M, but is limited in that the disk format is unique to Apple. This inhibits the exchange of software, which is distressing since one of the main advantages of CP/M is the exteall characters). D disconnect the phone (hang up) (Micromodem II only). Allowable secondary options are: A answer mode. O originate mode. D hang up after execution of previous options. T go to terminal mode after previous options. E go ;OFF HOOK, 110 BAUD, CAR. ON, ORIG. ANSWMOD EQU 8AH ;OFF HOOK, 110 BAUD, CAR. ON, ANSW. HANGUP EQU 0 ;ON HOOK OFHKFLG EQU 8DH ;OFF HOOK BYTE ; ;IF YOU ARE USING AN EXTERNAL MODEM ;CHANGE THESE EQUATES FOR YOUR MODEM PORT REQUIREMENTS ; INITREQ EQISTENSEN IN 1977, THIS PROGRAM HAS BECOME ;THE STANDARD PROTOCOL FOR CP/M TRANSFER. ;SEVERAL OTHERS HAVE CONTRIBUTED SIGNIFICANT ;ENHANCEMENTS INCLUDING: ; KEITH PETERSEN ; JIM BELL ; BOB MATHIAS ; ;NOTE: THIS FILE WILL ASSEMBLE, WITHOUT NEED FOR hen done. MODEM SAT.110 C:BYE.ASM ==> sent a file in answer mode, at 110 baud, dropping back into terminal mode when done. Get the file from drive C: MODEM C ==> dial a number to be asked for and connect with the computer at the oPORTS THE FOLLOWING APPLE MODEM CONFIGURATIONS: ; 1)DC HAYS MICROMODEM II ; 2)EXTERNAL MODEM THROUGH ONE OF THE FOLLOWING: ; a) CCS 7710 SERIAL INTERFACE ; b) SSM SERIAL INTERFACE ; c) APPLE COMMUNICATIONS INTERFACE ; d) APPLE SERIAL INTERFACE ; to echo mode after previous options. Q quiet mode, no message displays. R show characters received. S show characters sent. V view the file sent/received, as it goes/comes. The baud rates may be switched on the Micromodem and Com card PMODEM.DOC" * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ;PLEASE PASS ON MODS, BUGS, ETC, SO YOUR ;FIXES OR ENHANCEMENTS MAY BE SHARED BY ALL, ; TO: ; Gordon Banks ; 5715 S. Drexel #209 ; Chicago, IL 60637 ; (312) 324-6194 ;EDITING, TO WORK WITH A D.C. HAYES MICROMODEM II. ;IF YOU HAVE ANOTHER MODEM, YOU MUST CHANGE THE ;EQUATES TO FALSE FOR MMII AND TRUE FOR YOUR MODEM. ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * THIS PROGRAM DOCUMENTED IN "Ather end. (will drop into terminal mode with defaults set (originate, 300 baud)). The following control characters are active in terminal mode: ctrl-E ==> exit to CP/M, but don't hang up. ctrl-D ==> disconnect (hang up) (Micromodem only) ;DEFINE FALSE AND TRUE ; FALSE EQU 0 TRUE EQU NOT FALSE ; STDCPM EQU TRUE ;TRUE, IS STANDARD CP/M ; BASE EQU 0 ;CP/M BASE ADDRESS ; ;NOTE: IF DC HAYES THEN BAUD RATE DEFAULTS TO ;300 - 1 STOP BIT. DO NOT CHANGE NEXT EQUATES ; ORIGMOD EQU 8EH; ; APMODEM.ASM V2.0 ; WARD CHRISTENSEN'S CP/M ; MODEM FILE TRANSFER PROGRAM ; Modified for the Apple ][ ; BY GORDON BANKS ; 2/17/81 ; ;CP/M - CP/M FILE TRANSFER PROGRAM, AND ;TERMINAL PROGRAM. ; ; ORIGINALLY WRITTEN AND CONCEIVED BY WARD ;CHRby specifying .300 or .110 after the last of the secondary options in the command line. Examples: MODEM ROVT FILE.COM ==> receive a file in originate mode, viewing it as it comes in and save it in FILE.COM. Drop into terminal mode w ; ; ---------- ; ; 12/18/80 ;ADAPTED FOR THE APPLE ][ COMPUTER RUNNING CP/M WITH ;THE Z-80 SOFTCARD BY CHANGING THE EQUATES FOR THE ;VARIOUS APPLE MODEM CONFIGURATIONS AND CHANGING THE ;IN AND OUT STATEMENTS TO LDA AND STA. (GORDON BANKS) ;IT SUP. I will be happy to answer any questions. Happy modeming! Gordon Banks 5715 S. Drexel #209 Chicago, IL 60637 (312) 324-6194 Enclose SASE for mail replies. U FALSE ;TRUE, IF MODEM PORT INIT. REQ'D ; ;APPLE MODEM TYPES EQUATES MMII EQU TRUE ;TRUE, IF USING D.C. HAYES MICROMODEM ][ CCS EQU FALSE ;TRUE, USING CCS 7710 SERIAL INTERFACE COMCARD EQU FALSE ;TRUE, USING APPLE COMMUNICATIONS CARD SSM EQU FALSE CPI EXITCHR ;TIME TO END? JZ CKDIS ;YES, CK DISCONN CPI DISCCHR ;DISCONNECT REQUEST? JZ DISCONN ;YES, DO IT IF TIMESHR ORI 80H ;FORCE BIT 7 TO HIGH ENDIF ;TIMESHR STA MODDATP ;SEND THE CHAR ; ;SEE IF CHAR FROM LINE ; TERML LDA MODCTLP ;CB+1 ;GET PRIMARY OPTION CPI 'H' ;MODEM H(ELP)? JZ HELP ;..YES, GIVE HELP CPI 'X' ;MODEM X(AMPLES)? JZ EXAM ;GIVE EXAMPLES CPI 'C' ;AUTO DIAL OPTION JZ CONNCT ;DIAL ; ;SAVE PRIMARY OPTION, VALIDATE SECONDARY OPT. ; RTNC CALL PROCOPT ; ;IA PORT OF CCS ACIA (MOT 6850) ENDIF ;CCS ; IF COMCARD ;APPLE COMMUNCATIONS CARD MODCTLP EQU 0E0AEH ;STATUS MODDATP EQU 0E0AFH ;DATA ENDIF ;COMCARD ; IF MMII ;DC HAYES MICROMODEM ][ MODCTLP EQU 0E0A6H ;STATUS PORT MODCTL2 EQU 0E0A5H ;2ND STRACTERS ;DOWN THE LINE, AND DISPLAYS CHARACTERS ;RECEIVED FROM THE LINE. THIS MAKES IT ;SUITABLE FOR COMMUNICATION WITH TIME SHARING ;COMPUTERS, CBBS'S, OR ANOTHER PROGRAM ;RUNING "MODEM E" (ECHO MODE) ; ;TYPE THE "EXITCHR" (ORIGINALLY CTL-E) TO EXND OF TRANSMISSION ACK EQU 6 ;ACKNOWLEDGE NAK EQU 15H ;NEG ACKNOWLEDGE CAN EQU 18H ;CANCEL LF EQU 10 ;LINEFEED CR EQU 13 ;CARRIAGE RETURN ; ORG BASE+100H ; ;INIT PRIVATE STACK LXI H,0 ;HL=0 DAD SP ;HL=STACK FROM CP/M SHLD STACK ;..SAVE IT ;TRUE, USING SSM SERIAL INTERFACE ; ;the Apple serial card apparently has the same protocol for DATA ;and STATUS as the communication card. ;N.B.-->I have not tested this program for the SSM or ;Apple serial interface, but according to documentation N ;GET PRIMARY OPTION ; CPI 'C' ;AUTO DIAL JZ TERM ;DROP INTO TERMINAL MODE ; CPI 'E' ;TERMINAL IN ECHO JZ TRMECHO ;..MODE? ; CPI 'T' ;TERMINAL.. JZ TERM ;..MODE? ; CPI 'D' JZ DISCONN ; CPI 'S' ;SEND.. JZ SENDFIL ;..A FILE? NIT THE MODEM OR SERIAL PORT ; CALL INITMOD ; ;MOVE THE FILENAME FROM FCB 2 TO FCB 1 ; CALL MOVEFCB ; ;GOBBLE UP GARBAGE CHARS FROM THE LINE ;PRIOR TO RECEIVE OR SEND ; LDA MODDATP LDA MODDATP ; ;JMP TO APPROPRIATE FUNCTION ; LDA OPTIOATUS PORT MODDATP EQU 0E0A7H ;DATA PORT ENDIF ;MMII ; IF SSM ;SSM INTERFACE MODCTLP EQU 0E0A4H ;STATUS MODDATP EQU 0E0A5H ;DATA ENDIF ;SSM ; MODSNDB EQU 2 ;BIT TO TEST FOR SEND MODSNDR EQU 2 ;VALUE WHEN READY MODRCVB EQU 1 ;BIT TO TEST FOR IT. ;OR THE "DISCCHR" (ORIGINALLY CTL-D) TO DISCONN. ; ;A FUTURE ENHANCEMENT WILL BE TO WRITE THE ;RECEIVED DATA IN MEMORY, AND ALLOW IT TO ;BE WRITTEN TO DISK ; TERM CALL STAT ;LOCAL CHAR KEYED? JZ TERML ;..NO, CHECK LINE CALL KEYIN ;GET CHAR LXI SP,STACK ;SP=MY STACK CALL START ;GO PRINT ID DB 'APPLE ][ MODEM V2.0 as of ' DB '2/17/81',CR,LF,'$' ; START POP D ;GET ID MESSAGE MVI C,PRINT CALL BDOS ;PRINT ID MESSAGE ; ;INITIALIZE THE JMPS TO CP/M BIOS ; CALL INITADR ; LDA FI have ;been able to obtain, they should work using these equates. ; INITC1 EQU 03 ;1ST INIT CHAR TO CTL PORT INITC2 EQU 17 ;2ND INIT CHAR TO CTL PORT ; IF CCS ;CCS CARD MODCTLP EQU 0E0A0H ;STATUS PORT OF CCS ACIA MODDATP EQU 0E0A1H ;DAT ; CPI 'R' ;RECEIVE.. JZ RCVFIL ;..A FILE? ; ;INVALID OPTION ; JMP BADOPT ; * * * * * * * * * * * * * * * * * * * * * * * * TERM: TERMINAL MODE * * * * * * * * * * * * * * * * * * * * * * * * ; ;THIS PROGRAM SIMPLY SENDS KEYED CHARE TERMINALS TO ;HAVE BIT 7 HIGH (MARKING), SO IN THE TERMINAL ;MODE WE FORCE IT TO HIGH IF THE FOLLOWING OPTION ;IS SELECTED: ; TIMESHR EQU FALSE ;TRUE TO MAKE BIT 7 HIGH ; ;DEFINE ASCII CHARACTERS USED ; SOH EQU 1 ;START OF HEADER EOT EQU 4 ;ERECEIVE MODRCVR EQU 1 ;VALUE WHEN READY ; ERRLIM EQU 10 ;MAX ALLOWABLE ERRORS EXITCHR EQU 'E'-40H ;CTL-E EXIT FROM T OR C DISCCHR EQU 'D'-40H ;CTL-D DISCONNECTS MODEM T/E ; FASTCLK EQU FALSE ;TRUE FOR 4 MHZ CLOCK ; ;SOME TIME-SHARE COMPUTERS REQUIREAD STATUS ANI MODRCVB ;ISOLATE BIT CPI MODRCVR ;READY? JNZ TERM ;..NO, LOOP LDA MODDATP ;READ DATA ANI 7FH ;STRIP PARITY BIT CALL TYPE ;TYPE IT JMP TERM ;LOOP ; * * * * * * * * * * * * * * * * * * * * * * * * TRMECHO: TERMINAL WITH ',CR,LF,0 ; ;DIDN'T GET VALID HEADER - PURGE THE LINE, ;THEN SEND NAK. ; RCVSERR MVI B,1 ;WAIT FOR 1 SEC.. CALL RECV ;..WITH NO CHARS JNC RCVSERR ;LOOP UNTIL SENDER DONE MVI A,NAK ;SEND.. CALL SEND ;..THE NAK LDA ERRCT ;ABORT IF.. INR A ;.THE FILE CALL MAKEFIL ;..THEN MAKE NEW CALL ILPRT ;PRINT: DB 'FILE OPEN, READY TO RECEIVE',CR,LF,0 ; RCVLP CALL RCVSECT ;GET A SECTOR JC RCVEOT ;GOT EOT CALL WRSECT ;WRITE THE SECTOR CALL INCRSNO ;BUMP SECTOR # CALL SENDACK ;ACK THE SECTOR , CK DISCONN, EXIT CPI DISCCHR ;DISCONN? JZ DISCONN ;..YES, DO IT. STA MODDATP ;SEND CHAR CALL TYPE ;ECHO IT LOCALLY JMP TRMECHO ;..AND LOOP ; ;GOT CHAR FROM LINE ; LINECHR LDA MODDATP ;GET CHAR STA MODDATP ;ECHO IT ANI 7FH ;STRIP PARITY H ;GET SOH? JZ RCVSOH ;..YES ; ;EARLIER VERS. OF MODEM PROG SENT SOME NULLS - ;IGNORE THEM ; ORA A ;00 FROM SPEED CHECK? JZ RCVSQ ;YES, IGNORE IT CPI EOT ;END OF TRANSFER? STC ;RETURN WITH CARRY.. RZ ;..SET IF EOT ; ;DIDN'T GET SOH OR S ;SEND CKSUM CALL GETACK ;GET THE ACK JC SENDRPT ;REPEAT IF NO ACK JMP SENDLP ;LOOP UNTIL EOF ; ;FILE SENT, SEND EOT'S ; SENDEOF MVI A,EOT ;SEND.. CALL SEND ;..AN EOT CALL GETACK ;GET THE ACK JC SENDEOF ;LOOP IF NO ACK JMP DONE ;ALL DONEECHO * * * * * * * * * * * * * * * * * * * * * * * * ; ;TERMINAL PROGRAM WITH ECHO - SEE NOTES ;UNDER "TERM" ABOVE ; ;C A U T I O N DON'T RUN WITH BOTH COMPUTERS ;IN "ECHO" MODE - LINE ERRORS (OR ANY CHAR) ;WILL BE ECHOED BACK AND FORTH AD I * SUBROUTINES * * * * * * * * * * * * * * * * * * * * * * * * ; ; ;----> RCVSECT: RECEIVE A SECTOR ; ;RETURNS WITH CARRY SET IF EOT RECEIVED. ; RCVSECT XRA A ;GET 0 STA ERRCT ;INIT ERROR COUNT ; RCVRPT LDA QFLG ;QUIET? ORA A JZ RCVS JMP RCVLP ;LOOP UNTIL EOF ; ;GOT EOT ON SECTOR - FLUSH BUFFERS, END ; RCVEOT CALL WRBLOCK ;WRITE THE LAST BLOCK CALL SENDACK ;ACK THE SECTOR CALL CLOSFIL ;CLOSE THE FILE JMP DONE ;ALL DONE ; * * * * * * * * * * * * * * * * * * * * * * * BIT CALL TYPE ;TYPE IT JMP TRMECHO ;LOOP ; * * * * * * * * * * * * * * * * * * * * * * * * SENDFIL: SENDS A CP/M FILE * * * * * * * * * * * * * * * * * * * * * * * * ; ;THE CP/M FILE SPECIFIED IN THE MODEM COMMAND ;IS TRANSFERRED OVER EOT - ; MOV B,A ;SAVE CHAR LDA VSEEFLG ;VIEWING.. ORA A ;..MODE? JZ RCVSEH ;YES, PRT.MSG LDA QFLG ;QUIET.. ORA A ;..MODE? JZ RCVSERR ;YES, SKIP MSG RCVSEH MOV A,B ;GET CHAR CALL HEXO ;SHOW IN HEX CALL ILPRT ;PRINT: DB 'H RCD, NOT SOH ; * * * * * * * * * * * * * * * * * * * * * * * * RCVFIL: RECEIVE A FILE * * * * * * * * * * * * * * * * * * * * * * * * ; ;RECEIVES A FILE IN BLOCK FORMAT AS SENT ;BY ANOTHER PERSON DOING "MODEM S FN.FT". ; RCVFIL CALL ERASFIL ;ERASE NFINITUM. ; TRMECHO LDA MODCTLP ;GET STATUS ANI MODRCVB ;ISOLATE READY BIT CPI MODRCVR ;ARE WE READY? JZ LINECHR ;YES, READ THE CHR CALL STAT ;CHECK LOCAL KB JZ TRMECHO ;..NO CHAR CALL KEYIN ;GET LOCAL CHAR CPI EXITCHR ;END? JZ CKDIS ;YESQ ;YES, NO STAT MSG. CALL ILPRT ;PRINT: DB 'AWAITING #',0 LDA SECTNO ;GET SECTOR # INR A ;(REAL INR LATER) CALL HEXO ;PRINT IN HEX CALL CRLF ;..THEN CRLF ; RCVSQ MVI B,10 ;10 SEC TIMEOUT CALL RECV ;GET SOH/EOT JC RCVSTOT ;TIMEOUT CPI SO WAITNAK ;..FOR INITIAL NAK ; SENDLP CALL RDSECT ;READ A SECTOR JC SENDEOF ;SEND EOF IF DONE CALL INCRSNO ;BUMP SECTOR # XRA A ;ZERO ERROR.. STA ERRCT ;..COUNT ; SENDRPT CALL SENDHDR ;SEND A HEADER CALL SENDSEC ;SEND DATA SECTOR CALL SENDCKTHE PHONE TO ANOTHER ;COMPUTER RUNNING MODEM WITH THE "R" (RECEIVE) ;OPTION. THE DATA IS SENT ONE SECTOR AT A ;TIME WITH HEADERS AND CHECKSUMS, AND RE- ;TRANSMISSION ON ERRORS. ; SENDFIL CALL OPENFIL ;OPEN THE FILE MVI E,80 ;WAIT 80 SEC.. CALL.WE HAVE REACHED.. STA ERRCT ;..THE ERROR.. CPI ERRLIM ;..LIMIT? JC RCVRPT ;..NO, TRY AGAIN ; ;10 ERRORS IN A ROW - ; LDA VSEEFLG ;VIEWING.. ORA A ;..FILE? JZ RCVCKQ ;YES, ASK RETRY/QUIT LDA QFLG ;QUIET.. ORA A ;..MODE? JZ RCVSABT ;AB CARRY CLEAR IF ACK RECEIVED. ;IF AN ACK IS NOT RECEIVED, THE ERROR COUNT ;IS INCREMENTED, AND IF LESS THAN "ERRLIM", ;CARRY IS SET AND CONTROL RETURNS. IF THE ;ERROR COUNT IS AT "ERRLIM", THE PROGRAM ;ABORTS IF IN "QUIET" MODE, OR ASKS THE ;USER FOR CALL ILPRT DB '++CKSUM++ ',0 JMP RCVPRN ;PRINT ERROR # ; ;PREV SECT REPEATED, DUE TO THE LAST ACK ;BEING GARBAGED. ACK IT SO SENDER WILL CATCH UP ; RECVACK CALL SENDACK ;SEND THE ACK, JMP RCVSECT ;GET NEXT BLOCK ; ;SEND AN ACK FOR THE SECTET BLOCK #, BLOCK # COMPLEMENTED ; RCVSOH MVI B,1 ;TIMEOUT = 1 SEC CALL RECV ;GET SECTOR JC RCVSTOT ;GOT TIMEOUT MOV D,A ;D=BLK # MVI B,1 ;TIMEOUT = 1 SEC CALL RECV ;GET CMA'D SECT # JC RCVSTOT ;TIMEOUT CMA ;CALC COMPLEMENT CMP D ;GOOD S NON-FATAL MSGS. ; SENDSEC MVI A,1 ;SHOW NOW AT DATA.. STA DATAFLG ;..FOR VIEW COMMAND MVI C,0 ;INIT CKSUM LXI H,BASE+80H ;POINT TO BUFFER SENDC MOV A,M ;GET A CHAR CALL SEND ;SEND IT INR L ;POINT TO NEXT CHAR JNZ SENDC ;LOOP IF <100H XRA UM OK? JNZ RCVCERR ;NO, ERROR ; ;GOT A SECTOR, IT'S A DUP IF = PREV, ; OR OK IF = 1 + PREV SECTOR ; LDA RCVSNO ;GET RECEIVED MOV B,A ;SAVE IT LDA SECTNO ;GET PREV CMP B ;PREV REPEATED? JZ RECVACK ;ACK TO CATCH UP INR A ;CALC NEXT SECTOR #ORT ; RCVCKQ CALL CKQUIT ;RETRY/QUIT? JZ RCVSECT ;TRY AGAIN ; RCVSABT CALL CLOSFIL ;KEEP WHATEVER WE GOT CALL ERXIT DB '++UNABLE TO RECEIVE BLOCK' DB CR,LF,'++ABORTING++$' ; ;TIMEDOUT ON RECEIVE ; RCVSTOT LDA VSEEFLG ;VIEWING.. ORA A ;..M;PRINT: DB 'SEND # ',0 LDA SECTNO ;PRINT.. CALL HEXO ;..SECT # CALL CRLF ;..THEN CR/LF ; SENDHNM MVI A,SOH ;SEND.. CALL SEND ;..SOH, LDA SECTNO ;THEN SEND.. CALL SEND ;..SECTOR # LDA SECTNO ;THEN SECTOR # CMA ;..COMPLEMENTED.. CALL SOR ; SENDACK MVI A,ACK ;GET ACK CALL SEND ;..AND SEND IT RET ; ;----> SENDHDR: SEND THE SECTOR HEADER ; ;SEND: (SOH) (BLOCK #) (COMPLEMENTED BLOCK #) ; SENDHDR LDA QFLG ;QUIET.. ORA A ;..MODE? JZ SENDHNM ;YES, SKIP STATUS MSG. CALL ILPRT ECTOR #? JZ RCVDATA ;YES, GET DATA ; ;GOT BAD SECTOR # ; LDA VSEEFLG ;VIEWING.. ORA A ;..MODE? JZ RCVBSE ;..YES, PRT MSG LDA QFLG ;QUIET.. ORA A ;..MODE? JZ RCVSERR ;..YES, NO MSG ; RCVBSE CALL ILPRT ;PRINT: DB '++BAD SECTOR # IN HDR',A ;SHOW NOT INTO DATA.. STA DATAFLG ;..FOR VIEW COMMAND RET ;FROM SENDSEC ; ;----> SENDCKS: SEND THE CHECKSUM ; SENDCKS MOV A,C ;SEND THE.. CALL SEND ;..CHECKSUM RET ;FROM SENDCKS ; ;----> GETACK: GET THE ACK ON THE SECTOR ; ;RETURNS WITH CMP B ;MATCH? JNZ ABORT ;NO MATCH - STOP SENDER, EXIT RET ;CARRY OFF - NO ERRORS ; ;GOT CKSUM ; RCVCERR LDA VSEEFLG ;VIEWING.. ORA A ;..MODE? JZ RCVCPR ;..YES, PRT MSG LDA QFLG ;QUIET.. ORA A ;..MODE? JZ RCVSERR ;YES, NO MSG ; RCVCPODE? JZ RCVSPT ;YES, PRT MSG LDA QFLG ;QUIET.. ORA A ;..MODE? JZ RCVSERR ;YES, NO MSG ; RCVSPT CALL ILPRT DB '++TIMEOUT++ ',0 ; RCVPRN LDA ERRCT ;PRINT ERROR.. CALL HEXO ;..COUNT CALL CRLF JMP RCVSERR ;BUMP ERR CT, ETC. ; ;GOT SOH - GEND ;..SECTOR # RET ;FROM SENDHDR ; ;----> SENDSEC: SEND THE DATA SECTOR ; ;WHILE SENDING THE SECTOR, THE "DATAFLG" IS SET ;SUCH THAT IF "V" (VIEW THE FILE) WAS REQUESTED, ;THE "SHOW" ROUTINE WILL PRINT THE DATA, BUT NOT ;THE HDR OR CKSUM, OR ANYVSTOT ;TIMEOUT MOV M,A ;STORE CHAR INR L ;DONE? JNZ RCVCHR ;NO, LOOP ; ;VERIFY CHECKSUM ; MOV D,C ;SAVE CHECKSUM XRA A ;SHOW.. STA DATAFLG ;..END OF DATA MVI B,1 ;TIMEOUT LEN. CALL RECV ;GET CHECKSUM JC RCVSTOT ;TIMEOUT CMP D ;CHECKSCR,LF,0 JMP RCVSERR ;BUMP ERROR CT. ; RCVDATA MOV A,D ;GET SECTOR # STA RCVSNO ;SAVE IT MVI A,1 ;SHOW.. STA DATAFLG ;GETTING DATA MVI C,0 ;INIT CKSUM LXI H,BASE+80H ;POINT TO BUFFER RCVCHR MVI B,1 ;1 SEC TIMEOUT CALL RECV ;GET CHAR JC RCR QUIT/RETRY IF NOT. ; GETACK MVI B,10 ;WAIT 10 SECONDS MAX CALL RECVDG ;RECV W/GARBAGE COLLECT JC GETATOT ;TIMED OUT CPI ACK ;OK? (CARRY OFF IF =) RZ ;YES, RET FROM GETACK MOV B,A ;SAVE CHAR LDA QFLG ;QUIET.. ORA A ;..MODE? JZ ACKERR ;. MOV A,C ;GET COUNT CPI 16 ;DONE? JZ RDBFULL ;..YES, BUFF IS FULL JMP RDSECLP ;READ MORE ; REOF MVI A,1 STA EOFLG ;SET EOF FLAG MOV A,C ; ;BUFFER IS FULL, OR GOT EOF ; RDBFULL STA SECINBF ;STORE SECTOR COUNT LXI H,DBUF ;INIT BUFFER.. S---> OPENFIL: OPENS THE FILE TO BE SENT ; OPENFIL LXI D,FCB ;POINT TO FILE MVI C,OPEN ;GET FUNCTION CALL BDOS ;OPEN IT INR A ;OPEN OK? JNZ OPENOK ;..YES CALL ERXIT ;..NO, ABORT DB 'CAN''T OPEN FILE$' ; OPENOK CALL ILPRT ;PRINT: DB 'FILE O ;KEEP ON TRYIN' ; CSABORT CALL ERXIT DB 'CAN''T SEND SECTOR ' DB '- ABORTING',CR,LF,'$' ; ;TIMEOUT GETTING ACK ; GETATOT LDA QFLG ;QUIET.. ORA A ;..MODE? JZ ACKERR ;YES, NO MSG CALL ILPRT ;PRINT: DB 'TIMEOUT ON ACK',CR,LF,0 JMP ACKERR OCK LDA EOFLG ;GET EOF FLAG CPI 1 ;IS IT SET/ STC ;TO SHOW EOF RZ ;GOT EOF MVI C,0 ;SECTORS IN BLOCK LXI D,DBUF ;TO DISK BUFFER ; RDSECLP PUSH B PUSH D MVI C,STDMA ;SET DMA.. CALL BDOS ;..ADDR LXI D,FCB MVI C,READ CALL BDOS POP NI 5FH ;MAKE UPPER CASE CPI 'Y' ;WANT ERASED? JNZ CKDIS ;QUIT IF NOT ERASE ; ;ERASE OLD FILE ; LXI D,FCB ;POINT TO FCB MVI C,ERASE ;GET BDOS FNC CALL BDOS ;DO THE ERASE RET ;FROM "ERASFIL" ; ;----> MAKEFIL: MAKES THE FILE TO BE RECEIVED .YES, NO MSG MOV A,B ;GET CHAR CALL HEXO ;PRINT IN HEX CALL ILPRT ;PRINT: DB 'H RCD, NOT ACK',CR,LF,0 ; ;TIMEOUT OR ERROR ON ACK - BUMP ERROR COUNT ; ACKERR LDA ERRCT ;GET COUNT INR A ;BUMP IT STA ERRCT ;SAVE BACK CPI ERRLIM ;AT LIMIT? INR A ;CLOSE OK? RNZ ;..YES, RETURN CALL ERXIT ;..NO, ABORT DB 'CAN''T CLOSE FILE$' ; ;----> RDSECT: READS A SECTOR ; ;FOR SPEED, THIS ROUTINE BUFFERS UP 16 ;SECTORS AT A TIME. ; RDSECT LDA SECINBF ;GET # SECT IN BUFF. DCR A ;DECREMENT.. PEN, EXTENT LENGTH: ',0 LDA FCB+15 ;GET # SECTORS CALL HEXO ;PRINT IN HEX CALL ILPRT ;PRINT: DB 'H',CR,LF,0 RET ; ;----> CLOSFIL: CLOSES THE RECEIVED FILE ; CLOSFIL LXI D,FCB ;POINT TO FILE MVI C,CLOSE ;GET FUNCTION CALL BDOS ;CLOSE IT ; ABORT LXI SP,STACK ; ABORTL MVI B,1 ;1 SEC. W/O CHARS. CALL RECV JNC ABORTL ;LOOP UNTIL SENDER DONE MVI A,NAK ;NEGATIVE ACK CALL SEND ;TELL SENDING END CALL ILPRT ;EXIT WITH ABORT MSG DB 'MODEM PROGRAM CANCELLED',CR,LF,0 JMP CKDIS ;CHED POP B ORA A ;READ OK? JZ RDSECOK ;YES DCR A ;EOF? JZ REOF ;GOT EOF ; ;READ ERROR ; CALL ERXIT DB '++FILE READ ERROR$' ; RDSECOK LXI H,80H ;ADD LENGTH OF ONE SECTOR... DAD D ;...TO NEXT BUFF XCHG ;BUFF TO DE INR C ;MORE SECTORS? ; MAKEFIL LXI D,FCB ;POINT TO FCB MVI C,MAKE ;GET BDOS FNC CALL BDOS ;TO THE MAKE INR A ;FF=BAD? RNZ ;OPEN OK ;DIRECTORY FULL - CAN'T MAKE FILE CALL ERXIT DB '++ERROR - CAN''T MAKE FILE',CR,LF DB '++DIRECTORY MUST BE FULL',CR,LF,'$' ; ;-RC ;NOT AT LIMIT ; ;REACHED ERROR LIMIT ; LDA VSEEFLG ;VIEWING.. ORA A ;..FILE? JZ GACKV ;YES, ASK QUIT/RETRY LDA QFLG ;QUIET.. ORA A ;..MODE? JZ CSABORT ;..YES, NO MSG ; GACKV CALL CKQUIT ;SEE IF WANT TO QUIT STC ;TO SHOW NO ACK RZ STA SECINBF ;..IT JM RDBLOCK ;EXHAUSTED? NEED MORE. LHLD SECPTR ;GET POINTER LXI D,BASE+80H ;TO DATA CALL MOVE128 ;MOVE TO BUFFER SHLD SECPTR ;SAVE BUFFER POINTER RET ;FROM "READSEC" ; ;BUFFER IS EMPTY - READ IN ANOTHER BLOCK OF 16 ; RDBLL BLOCK MVI C,SRCHF ;SEE IF IT.. CALL BDOS ;..EXISTS INR A ;FOUND? RZ ;..NO, RETURN CALL ILPRT ;PRINT: DB '++FILE EXISTS, TYPE Y TO ERASE: ',0 CALL KEYIN ;GET CHAR PUSH PSW CALL TYPE ;ECHO CALL CRLF ;BACK TO START OF LINE POP PSW ACK FOR DISCONN. ; ;----> INCRSNO: INCREMENT SECTOR # ; INCRSNO LDA SECTNO ;INCR.. INR A ;..SECT.. STA SECTNO ;..NUMBER RET ; ;----> ERASFIL: ERASE THE INCOMING FILE. ; ;IF IT EXISTS, ASK IF IT MAY BE ERASED. ; ERASFIL LXI D,FCB ;POINT TO CTHLD SECPTR ;..POINTER LXI D,BASE+80H ;RESET.. MVI C,STDMA ;..DMA.. CALL BDOS ;..ADDR JMP RDSECT ;PASS SECT TO CALLER ; ;----> WRSECT: WRITE A SECTOR ; ;WRITES THE SECTOR INTO A BUFFER. WHEN 16 ;HAVE BEEN WRITTEN, WRITES THE BLOCK TO DISK. ; TIMEOUT-NAK FROM THE RECEIVER. ;(E) CONTAINS THE # OF SECONDS TO WAIT. ; WAITNAK LDA VSEEFLG ;VIEWING? ORA A JZ WAITNPR ;PRINT MSG LDA QFLG ;QUIET.. ORA A ;..MODE? JZ WAITNLP ;YES, SKIP MSG ; WAITNPR CALL ILPRT ;PRINT: DB 'AWAITING INITIA ; ;GOT CHAR FROM MODEM ; MCHAR LDA MODDATP ;READ THE CHAR POP D ;RESTORE DE ; ;CALC CHECKSUM ; PUSH PSW ;SAVE THE CHAR ADD C ;ADD TO CHECKSUM MOV C,A ;SAVE CHECKSUM ; ;CHECK IF MONITORING REC'D DATA ; LDA RSEEFLG ;SEE RECEIVED.. ORA A;POINT TO DISK BUFF ; DKWRLP PUSH H PUSH D PUSH B MVI C,STDMA ;SET DMA CALL BDOS ;TO BUFFER LXI D,FCB ;THEN WRITE MVI C,WRITE ;..THE.. CALL BDOS ;..BLOCK POP B POP D POP H ORA A JNZ WRERR ;OOPS, ERROR LXI H,80H ;LENGTH OF 1 SECT NOMONOT ;..NO. ; MONOUT POP PSW ;GET THE CHAR PUSH PSW ;SAVE IT CALL SHOW ;SHOW IT ; NOMONOT POP PSW ;RESTORE CHAR PUSH PSW ;SAVE IT ADD C ;CALC CKSUM MOV C,A ;SAVE CKSUM SENDW LDA MODCTLP ;GET STATUS ANI MODSNDB ;ISOLATE READY BIT CPI LDA MODDATP ;..TOTALLY PURGE UART ; RECV PUSH D ;SAVE ; IF FASTCLK ;4MHZ? MOV A,B ;GET TIME REQUEST ADD A ;DOUBLE IT MOV B,A ;NEW TIME IN B ENDIF ; MSEC LXI D,50000 ;1 SEC DCR COUNT MWTI LDA MODCTLP ;CHECK STATUS ANI MODRCVB ;ISOLATE BI ;ENTRY POINT "WRBLOCK" FLUSHES THE BUFFER AT EOF. ; WRSECT LHLD SECPTR ;GET BUFF ADDR XCHG ;TO DE FOR MOVE LXI H,BASE+80H ;FROM HERE CALL MOVE128 ;MOVE TO BUFFER XCHG ;SAVE NEXT.. SHLD SECPTR ;..BLOCK POINTER LDA SECINBF ;BUMP THE.. INR FF, NOT DATA ; MONIN POP PSW ;..IS DATA, PUSH PSW ;GET IT, CALL SHOW ;..AND SHOW IT ; NOMONIN POP PSW ;RESTORE CHAR ORA A ;CARRY OFF: NO ERROR RET ;FROM "RECV" ; ;----> SEND: SEND A CHARACTER TO THE MODEM ; SEND PUSH PSW ;SAVE THE CHAR ; ;..DATA? JZ MONIN ;..YES ; ;CHECK IF "VIEWING" AND THIS IS A DATA CHAR ; LDA VSEEFLG ;VIEWING.. ORA A ;..DATA? JNZ NOMONIN ;..NO ; ;"VIEW" REQUESTED. SHOW THE CHAR IT IS DATA ; LDA DATAFLG ;GET DATA FLAG ORA A ;TEST IT JZ NOMONIN ;..O DAD D ;HL= NEXT BUFF XCHG ;TO DE FOR SETDMA DCR C ;MORE SECTORS? JNZ DKWRLP ;..YES, LOOP XRA A ;GET A ZERO STA SECINBF ;RESET # OF SECTORS LXI H,DBUF ;RESET BUFFER.. SHLD SECPTR ;..POINTER ; RSDMA LXI D,BASE+80H ;RESET.. MVI C,STDMA ;MODSNDR ;READY? JNZ SENDW ;..NO, WAIT POP PSW ;GET CHAR STA MODDATP ;OUTPUT IT RET ;FROM "SEND" ; ;----> WAITNAK: WAITS FOR INITIAL NAK ; ;TO ENSURE NO DATA IS SENT UNTIL THE RECEIVING ;PROGRAM IS READY, THIS ROUTINE WAITS FOR THE ;THE FIRSTT CPI MODRCVR ;READY? JZ MCHAR ;GOT CHAR DCR E ;COUNT.. JNZ MWTI ;..DOWN.. DCR D ;..FOR.. JNZ MWTI ;..TIMEOUT DCR B ;MORE SECONDS? JNZ MSEC ;YES, WAIT ; ;MODEM TIMED OUT RECEIVING ; POP D ;RESTORE D,E STC ;CARRY SHOWS TIMEOUT RET A ;..SECTOR #.. STA SECINBF ;..IN THE BUFF CPI 16 ;HAVE WE 16? RNZ ;NO, RETURN ; ;----> WRBLOCK: WRITES A BLOCK TO DISK ; WRBLOCK LDA SECINBF ;# SECT IN BUFFER ORA A ;0 MEANS END OF FILE RZ ;NONE TO WRITE MOV C,A ;SAVE COUNT LXI D,DBUF ;CHECK IF MONITORING SENT DATA ; LDA SSEEFLG ;CHECK IF MONITORING.. ORA A ;..SENT DATA JZ MONOUT ;..YES ; ;CHECK IF "VIEWING" THE FILE ; LDA VSEEFLG ;GET VIEW FLAG ORA A ;TEST IT JNZ NOMONOT ;NO LDA DATAFLG ;IS THIS ORA A ;..DATA? JZGARBAGE CHARACTERS ON THE ;LINE. FOR EXAMPLE, HAVING JUST SENT A SECTOR, ;CALLING RECVDG WILL DELETE ANY LINE-NOISE-INDUCED ;CHARACTERS "LONG" BEFORE THE ACK/NAK WOULD ;BE RECEIVED. ; RECVDG EQU $ ;RECEIVE W/GARBAGE DELETE LDA MODDATP ;GET A CHAR ..DMA.. CALL BDOS ;..ADDR RET ; WRERR CALL RSDMA ;RESET DMA TO NORM. CALL ILPRT ;PRINT: DB '++ERROR WRITING FILE',CR,LF,0 JMP ABORT ;EXIT ; ;----> RECV: RECEIVE A CHARACTER ; ;TIMEOUT TIME IS IN B, IN SECONDS. ENTRY VIA ;"RECVDG" DELETES L NAK',CR,LF,0 ; WAITNLP MVI B,1 ;TIMEOUT DELAY CALL RECV ;DID WE GET.. CPI NAK ;..A NAK? RZ ;YES, SEND BLOCK DCR E ;80 TRIES? JZ ABORT ;YES, ABORT JMP WAITNLP ;NO, LOOP ; ;----> INITADR: INIT'S CP/M BDOS ADDRESSES ; ;THIS ROUTINE FILLS LDA ANSWFLG ;ANSWER.. ORA A MVI B,ANSWMOD ;SET ANSWER MODE JZ INITM1 LDA ORIGFLG ;GET ORIGINATE FLAG ORA A MVI B,ORIGMOD ;SET ORIGINATE MODE JZ INITM1 LDA HOLDD ;NEITHER - GET LAST VALUE MOV B,A ;STORE IN"B ; INITM1: MOV A,B ;GET M ORA A JZ TRMECHO ;..YES ; ;FALL INTO 'CKDIS' ; ;----> CKDIS: CHECK IF DISCONNECT REQUESTED ; ;THIS ROUTINE IS JUMPED TO AT THE END OF ;PROCESSING, AND DISCONNECTS THE PHONE IF ;'D' WAS SPECIFIED AS A SUB-OPTION. ; CKDIS LDA DISCFLG ;CHECK 'D' : PROCESS COMMAND OPTIONS ; ;1) SAVES THE PRIMARY OPTION IN 'OPTION'; ;2) SCANS THE SUB-OPTION CHARACTERS, AND FOR ;EACH FOUND, ZEROS THE APPROPRIATE ENTRY IN ;THE OPTION TABLE. FOR EXAMPLE, IF 'D' IS ;CODED (DISCONNECT) THEN THE 'D' STORED AT ;'F,0 JMP EXIT ; ENDIF ; ;----> INITMOD: INITIALIZES THE MODEM ; ;THIS ROUTINE IS USED TO INITIALIZE SERIAL ;BOARDS, OR SETUP S-100 MODEM BOARDS. ;JUST RETURNS IF NO INITIALIZATION REQUIRED. ; INITMOD: ; IF INITREQ ;REQUIRE INIT? MVI A,INIQUIET FLAG ; ENDOPT LDA VSEEFLG ;VIEW.. ORA A ;..ASKED FOR? RNZ ;..NO, RET FROM 'PROCOPT' STA QFLG ;YES, NO HDR/CKSUM PRT RET ;FROM 'PROCOPT' ; ;DONE - CLOSE UP SHOP ; DONE LDA VSEEFLG ;VIEWING? ORA A JZ DONETC ;SHOW MSG LDA QFLG ;QUIIN THE ADDRESSES OF VARIOUS ;JMP AND CALL INSTRUCTIONS, SO THAT CP/M BDOS ;IS BYPASSED WHILE ACCESSING THE CONSOLE. THIS ;IS DONE TO ALLOW CHARACTERS SUCH AS CONTROL-C ;AND CONTROL-S TO BE KEYED WHILE IN TERMINAL ;MODE, WITHOUT CP/M INTERPRETING THEM POP PSW CPI CR JNZ CKDIS ;ASK AGAIN ; ;----> DISCONN: DISCONNECT THE PHONE ; DISCONN EQU $ ; IF MMII XRA A ;GET DISCONNECT VALUE STA MODCTL2 ;DISCONNECT ENDIF ; CALL ILPRT ;PRINT: DB '++DISCONNECTED++',0 JMP EXIT ; ;NO DISCONNECFLAG ORA A ;REQUESTED? ; IF MMII JNZ NDIS ;..NO, JUST EXIT ENDIF ; IF NOT MMII JNZ EXIT ENDIF ; ;AWAIT C/R TO DISC. SO WE DON'T LOSE THE PHONE ; CALL ILPRT DB CR,LF,'PRESS RETURN TO DISCONNECT:',0 CALL KEYIN PUSH PSW CALL CRLF DISCFLG' IS SET TO 0 SO IT CAN BE TESTED ;LATER. ; PROCOPT LXI D,FCB+1 ;TO PRIMARY OPT. LDAX D ;GET PRIMARY STA OPTION ;SAVE IT ; OPTLP INX D ;TO SECONDARY OPTION LDAX D ;GET CHAR ; ;IF YOU MOD THIS PROGRAM FOR >7 OPTIONS, ;YOU MUST CHANGE THTC1 ;GET 1ST INIT CHAR STA MODCTLP ;OUTPUT IT NOP ! NOP! NOP ;DELAY FOR USART NOP ! NOP MVI A,INITC2 ;GET 2ND INIT CHAR STA MODCTLP ;OUTPUT IT NOP ! NOP! NOP ;DELAY FOR USART NOP ! NOP ENDIF ; IF MMII CALL GETBAUD ;GET BAUD RATE ET ORA A ;..MODE? JZ DONECTE ;YES, CK TERM/ECHO ; DONETC CALL ILPRT DB CR,LF,'TRANSFER COMPLETE' DB CR,LF,0 ; ;CHECK IF TERMINAL OR ECHO SUB COMMAND ;WAS SPECIFIED ; DONECTE LDA TERMFLG ;TERM? ORA A JZ TERM ;..YES LDA ECHOFLG ;ECHO? . ; INITADR LHLD BASE+1 ;GET WARM BOOT ADDR LXI D,3 ;LENGTH OF A 'JMP' DAD D ;TO CONSOLE STAT SHLD VSTAT+1 ;MODIFY CALL DAD D ;TO CONSOLE IN SHLD VKEYIN+1 ;MODIFY CALL DAD D ;TO CONSOLE OUT SHLD VTYPE+1 ;MODIFY CALL RET ; ;----> PROCOPTT, TYPE MSG AS REMINDER THAT PHONE'S ;OFF HOOK ; IF MMII NDIS LDA QFLG ;QUIET.. ORA A ;..MODE? JZ EXIT ;..YES, NO MSG CALL ILPRT DB CR,LF,'++DON''T FORGET - THE MODEM IS ' DB 'NOT DISCONNECTED++',CR,LF DB 'USE "MODEM D" TO DISCONNECT',CR,LTCK CMP M ;FOUND THE OPTION? JNZ OPTNO ;NO, DON'T SET IT MVI M,0 ;SET THE OPTION JMP OPTLP ;GET NEXT OPTION ; OPTNO INX H ;TO NEXT DCR B ;MORE? JNZ OPTCK ;OPTION NOT IN TABLE JMP BADOPT ;SHOW BAD SUB OPTION ; ;IF "VIEW" WAS ASKED FOR, SET E FOLLOWING, SINCE ;THERE WON'T BE A ' ' AFTER THE OPTION ;IF A BAUD RATE WAS SPECIFIED. ; CPI ' ' ;NO MORE OPT'NS? JZ ENDOPT ;..YES ;SET THE APPROP. OPT: STORE 0 IN IT LXI H,OPTBL ;HL = ADDR OF 'OAQDSRV' MVI B,OPTBE-OPTBL ;OPT TABLE LEN ; OPODE STA HOLDD ;SAVE VALUE MOV A,C ;GET BAUD RATE INDICATOR ORA A ;ZEBO IF 110 BAUD MOV A,B ;GET MODE JZ OFFHOOK ;DO OFFHOOK ORI 1 ;SET 300 BAUD ;GO OFFHOOK IN REQUESTED (ORIG/ANSW) MODE ; OFFHOOK LXI H,4000 ;DELAY AMT ; OFFDLY DCR L PULSE COUNT FROM DIAL PULS1 MVI C,0 ;ON HOOK MOV A,C STA MODCTL2 ;GO ON HOOK CALL DELAY ;50 MS MVI C,80H ;OFF HOOK MOV A,C STA MODCTL2 ;GO OFF HOOK CALL DELAY ;50 MS DCR B ;COUNT DOWN 1 PULSE JNZ PULS1 ;NOT ZERO, MAKE ANOTHER PULSE NZ DECLP ;NO, LOOP RET ; ;INVALID BAUD RATE ; BADRATE CALL ERXIT DB '++INVALID BAUD RATE++$' ENDIF ;PMMI OR DCH ; ;THE FOLLOWING PROVIDES A RETURN FROM INITMOD IF NOT MMII AND NOT COMCARD RET ;**THIS MUST BE HERE** ENDIF ;NOT PMMI AND ,15H ;SET 1 STOP BIT INR C LXI D,-300 ;GET CONSTANT DAD D MOV A,H ORA L JNZ BADRATE ;INVALID ; GETBAU2 MOV A,B ;GET SET UP STA MODCTLP ;INITIALIZE MODEM FOR STOP BITS.. RET ;..DATA BITS, ETC. ENDIF ;DCH ; IF COMCARD ;APPLE COMMUNCANT REGISTERS ORA A ;SOMETHING THERE? JZ NONUM ;..NO, EXIT WITH ERROR CPI CR ;DONE? JZ GETCAR ;GET CARRIER MOV C,A ;SAVE IT CALL TYPE ;TYPE TO CONSOLE MOV A,C ;RESTORE TO A CPI 3AH ;IGNORE ALL BUT DIGITS JNC NXTDIG ;LOOP BACK CPI '0' IGIT INX D ;TO NEXT DIGIT CPI ' ' ;BLANK ONE? JZ DECLP ;..YES, SKIP IT CPI '0' ;VALIDATE IT JC BADRATE ;ERROR CPI '9'+1 ;VALIDATE JNC BADRATE ;ERROR SUI '0' ;MAKE DIGIT BINARY ; ;MULTIPLY PREV VALUE BY 10 ; MOV B,H ;SET UP FOR MOV C, JNZ OFFDLY DCR H JNZ OFFDLY STA MODCTL2 ;GO OFF HOOK RET ENDIF ;MMII ; IF MMII GETBAUD LDA FCB+9 ;GET FILETYPE CPI ' ' ;DEFAULT? JNZ GETBAU1 ;NO - DO BAUD RATE STUFF MVI C,1 ;SET 300 BAUD MVI B,15H ;SET 1 STOP BIT JMP GETBAU2 ; DIAL THE NUMBER CPI 8 ;BACKSPACE JZ DERD ;DECREMENT BUFFER STAX D ;..NO, STORE IN BUFFER INX D ;D:=D+1 CALL TYPE ;TYPE IT TO CONSOLE JMP GETDIG ;LOOP BACK FOR MORE INPUT DERD DCX D CALL TYPE ;BACKSPACE TO CONSOLE JMP GETDIG ;LOOP BACK DNOT DCH ; ;----> CONNCT: AUTODIAL ROUTINE FOR THE DC HAYES ; IF MMII CONNCT CALL ILPRT ;PRINT MESSAGE DB 'Number to dial: ',0 LXI D,NUMBUF ;POINT TO BUFFER GETDIG CALL KEYIN ;GET CHAR FROM KEYBOARD CPI CR ;IS IT END OF LINE? JZ DIAL ;..YES,TIONS CARD GETBAUD LDA FCB+9 ;GET FILETYPE CPI ' ' ;DEFAULT? JNZ GETBAU1 ;NO - DO BAUD RATE STUFF MVI B,11H ;300 BAUD STATUS CODE JMP GETBAU2 ; CONVERT BAUD RATE TO BINARY GETBAU1 CALL CVBIN ;CONVERT TO BINARY PUSH H ;SAVE BAUD RATE MVI B,5 JC NXTDIG MOV C,A CALL PULSE ;DIAL IT JMP NXTDIG ;LOOP BACK FOR MORE FROM BUFFER ; PULSE PUSH B ;SAVE BC MOV A,C MVI B,10 ;PRE LOAD PULSE REGISTER ANI 0FH ;KILL ASCII BIAS CPI 0 ;IF NUM A 0 THEN WANT 10 PULSES JZ PULS1 MOV B,A ;LOAD L ;MULTIPLY BY 10 DAD H ;MULTIPLY BY 2 DAD H ;X 2 = 4 DAD B ;+ 1 = 5 DAD H ;X 2 = 10 ADD L ;ADD IN DIGIT MOV L,A ;SAVE BACK JNZ DIGNC ;NO CARRY? INR H ;ADD IN CARRY ;CHECK IF DONE? DIGNC MOV A,E ;SEE IF PAST CPI FCB+12 ;..LAST DIGIT J ; CONVERT BAUD RATE TO BINARY GETBAU1 CALL CVBIN ;CONVERT TO BINARY PUSH H ;SAVE BAUD RATE MVI C,0 ;ANTICIPATE 110 BAUD MVI B,15H ;SET 2 STOP BITS LXI D,-110 ;GET CONSTANT DAD D ;SUBTRACT MOV A,H ORA L POP H JZ GETBAU2 ;110 BAUD MVI BIAL INX D ;D:=D+1 MVI B,CR ;EOLN MARKER MOV A,B STAX D ;STORE IT IN BUFFER CALL ILPRT DB CR,LF,'Dialing...',0 MVI B,OFHKFLG ;80H MOV A,B CALL DLTONE ;GET DIALTONE LXI D,NUMBUF ;POINT TO BUFFER NXTDIG LDAX D ;GET A DIGIT INX D ;INCREMELY) GETBAU2 MOV A,B ;GET SET UP STA MODCTLP ;STORE TO STATUS PORT RET ENDIF ;COMCARD ; IF COMCARD OR MMII ; ROUTINE TO CONVERT BAUD RATE TO BINARY ; CVBIN: LXI D,FCB+9 ;TO ASCII VALUE LXI H,0 ;INIT BINARY RESULT ; DECLP LDAX D ;GET ASCII D2H ;ANTICIPATE 110 BAUD LXI D,-110 ;GET CONSTANT DAD D ;SUBTRACT MOV A,H ORA L POP H JZ GETBAU2 ;110 BAUD MVI B,11H ;300 BAUD STATUS CODE INR C LXI D,-300 ;GET CONSTANT DAD D MOV A,H ORA L JNZ BADRATE ;INVALID RATE (300 OR 110 ON CALL KDELAY ;500 MS INTERDIGIT DELAY POP B ;RESTORE BC RET ; ; 50MS DELAY ROUTINE DELAY PUSH PSW PUSH B LXI B,5000 DELAY1 DCX B MOV A,B ORA C JNZ DELAY1 POP B POP PSW RET ; ;1 SEC DELAY ROUTINE KDELAY MVI L,15 KD1 DCR L JZ F JMP TYPE ;..THEN TYPE IT ; ;----> CKQUIT: QUIT/RETRY AFTER MULTIPLE ERRS. ; ;RETURNS W/ ZERO SET IF "RETRY" ASKED FOR ; CKQUIT XRA A ;ZERO.. STA ERRCT ;..ERROR COUNT CALL ILPRT ;PRINT: DB 'MULTIPLE ERRORS ENCOUNTERED. ' DB 'TYPE Q TO QUIT, A,')' ;THEN.. JMP CTYPE ;..')' AND RETURN. ; ;----> CTYPE: TYPES VIA CP/M SO TABS ARE EXPANDED ; CTYPE PUSH B ;SAVE.. PUSH D ;..ALL.. PUSH H ;..REGS MOV E,A ;CHAR TO E MVI C,WRCON ;GET BDOS FNC CALL BDOS ;PRIN THE CHR POP H ;RESTORE.. IT XRI 04 ;REVERSE LOGIC JNZ CERTIFY ;CARRIER FOUND...MAYBE NOPE CALL DELAY ;IT WASN'T A CARRIER DCR C ;COUNTDOWN JNZ GETCAR1 ;LOOP CALL ILPRT DB '++TIMED OUT LOOKING FOR CARRIER',CR,LF,0 CALL DISCONN ;HANG UP CERTIFY CALL KDELAY ;MAKIN CASE ;CBIOS CLOBBERS THEM. ; KEYIN PUSH B PUSH D PUSH H VKEYIN CALL $-$ ;ADDR SET AT INIT POP H POP D POP B ANI 7FH ;STRIP PARITY IF THERE RET ;FROM KEYIN ; ;----> HEXO: HEX OUTPUT ; HEXO PUSH PSW ;SAVE FOR RIGHT DIGIT RAR ;RIXT ;..AND EXTENT RET ; ;----> SHOW: SHOWS CHAR SENT/RECEIVED ; ;CR, LF, AND TAB ARE SHOWN. ALL OTHER ;NON-PRINTABLE CHARACTERS ARE SHOWN IN ;HEX AS (XX) ; SHOW CPI LF ;LF? JZ CTYPE ;..YES, TYPE IT CPI CR ;CR? JZ CTYPE ;..YES, TYPE IT CPIINIS CALL DELAY JMP KD1 FINIS RET ; DLTONE CALL OFFHOOK ;GO OFFHOOK CALL KDELAY CALL KDELAY CALL KDELAY CALL KDELAY ;WAIT 4 SEC BEFORE DIALING RET ; GETCAR CALL ILPRT DB CR,LF,'++AWAITING CARRIER',CR,LF,0 MVI C,30 ;WAIT 30 SEC FORSTS. ; TYPE PUSH PSW ;SAVE CHAR PUSH B ;AND OTHER REGISTERS PUSH D PUSH H MOV C,A ;FOR BIOS VTYPE CALL $-$ ;MODIFIED AT INIT POP H ;RESTORE REGISTERS POP D POP B POP PSW ;..AND CHAR RET ;FROM "TYPE" ; ;----> STAT: KEYBOARD STATUS POP D ;..ALL.. POP B ;..REGS RET ;FROM "CTYPE" ; CRLF MVI A,CR CALL TYPE MVI A,LF ; ;----> TYPE: TYPE VIA DIRECT CBIOS ACCESS ;WE ASSUME CBIOS MAY DESTROY SOME REGISTERS, ;SO SAVE THEM ALL. ; ;THIS ROUTINE BYPASSES CP/M'S CTL-S, CTL-C ;TEE SURE CARRIER IS REALLY THERE CALL KDELAY LDA MODCTLP ;CHECK STATUS ANI 04 ;ISOLATE NO CARRIER BIT XRI 04 ;REVERSE LOGIC JZ NOPE ;IT WAS SPURIOUS,LOOP BACK GOTCAR CALL ILPRT DB '++CARRIER DETECTED',CR,LF,0 JMP RTNC ;GO BACK TO START FOR TGHT.. RAR ;..JUSTIFY.. RAR ;..LEFT.. RAR ;..DIGIT.. CALL NIBBL ;PRINT LEFT DIGIT POP PSW ;RESTORE RIGHT ; NIBBL ANI 0FH ;ISOLATE DIGIT CPI 10 ;IS IS <10? JC ISNUM ;YES, NOT ALPHA ADI 7 ;ADD ALPHA BIAS ; ISNUM ADI '0' ;MAKE PRINTABLE 09 ;TAB JZ CTYPE ;..YES, TYPE IT CPI ' ' ;CTL-CHR? JC SHOWHEX ;YES, SHOW IN HEX CPI 7FH ;DEL? JC CTYPE ;NO, TYPE THE CHAR ; SHOWHEX PUSH PSW ;SAVE THE CHAR MVI A,'(' ;TYPE.. CALL CTYPE ;..'(' POP PSW ;THEN.. CALL HEXO ;..THE CHAR MVI CARRIER GETCAR1 MVI B,3 ;RESET MODEM MOV A,B STA MODCTLP MVI B,8DH ;OFF HOOK, ORIG., BUT NO CARRIER MOV A,B STA MODCTL2 ;RESET MODEM STATUS MVI B,0 MOV A,B CALL KDELAY ;WAIT AGAIN LDA MODCTLP ;CHECK STATUS ANI 04 ;ISOLATE NO CARRIER B; ;SAVE ALL REGISTERS, EXCEPT A, IN CASE ;CBIOS CLOBBERS THEM. ; STAT PUSH B PUSH D PUSH H VSTAT CALL $-$ ;ADDR SET AT INIT POP H POP D POP B ORA A ;0 => NOT READY RET ; ;----> KEYIN: KEYBOARD INPUT ; ;SAVE ALL REGISTERS, EXCEPT A, ;THAT MODEM FILENAME SEND (MODEM FN.FT S) SO THIS ;ROUTINE MOVES THE FILENAME FROM THE SECOND FCB ;TO THE FIRST ; MOVEFCB LXI H,FCB+16 ;FROM LXI D,FCB ;TO MVI B,16 ;LEN CALL MOVE ;DO THE MOVE XRA A ;GET 0 STA FCBSNO ;ZERO SECTOR # STA FCBEERMINAL MODE ; NONUM CALL ILPRT DB '++NO NUMBER WAS FOUND FOR DIALING++',CR,LF,0 JMP EXIT ENDIF ;MMII ; ;----> MOVEFCB: MOVES FCB(2) TO FCB ; ;I ATTEMPTED TO MAKE THE MODEM COMMAND 'NATURAL', ;I.E. MODEM SEND FILENAME (MODEM S FN.FT) RATHER R TO RETRY: ',0 CALL KEYIN ;QUIT/RETRY PUSH PSW CALL TYPE CALL CRLF POP PSW ANI 5FH ;MAKE UPPER CASE CPI 'R' ;RETRY? RZ ;'KEEP ON TRUCKIN' CPI 'Q' ;QUIT? JNZ CKQUIT ;NO, ASK AGAIN ORA A ;SET NON-ZERO RET ; ;----> ILPRT: INLINE Phow chars received',cr,lf DB ' S show chars sent',cr,lf DB ' V view file sent/received (no status)',cr,lf DB CR,LF,'FOR EXAMPLES, TYPE: MODEM X',cr,lf,0 JMP EXIT ; EXAM CALL ILPRT DB 'Send file, originate mode, 300 baud:',CR,LF DB ' MODEM SO CT # RECEIVED SECTNO DB 0 ;CURRENT SECTOR NUMBER ERRCT DB 0 ;ERROR COUNT HOLDD DB 8EH ;HOLD AREA - LAST DC HAYES CONT CHAR. ;FOLLOWING 3 USED BY DISK BUFFERING ROUTINES EOFLG DB 0 ;EOF FLAG (1=TRUE) SECPTR DW DBUF SECINBF DB 0 ;# OF SECTORS IN BUFFTO CONTINUE' DB CR,LF,0 CALL KEYIN ;GET ANY CHAR CPI 'C'-40H ;REBOOT? JZ EXIT ;YES. JMP ILPNEXT ;LOOP ; ILPRET XTHL ;RESTORE HL RET ;PAST MSG ; ;----> PRTMSG: PRINTS MSG POINTED TO BY (DE) ; ;A '$' IS THE ENDING DELIMITER FOR THE PRINT.,lf DB ' E to act as a computer (echo data)',cr,lf DB ' C to connect (Micromodem autodial)',cr,lf DB ' D to disconnect the phone ' DB '(Micromodem ][ only)',cr,lf DB ' H to print this help file' DB cr,lf,cr,lf,1 DB 'Secondary options:',cr,lf DATAFLG DB 0 ;AT HEADER, FIRST ; ; ;SUB-OPTION TABLE. IF AN OPTION IS IN EFFECT, ; THE CHARACTER IS SET TO BINARY 0 ; OPTBL EQU $ ANSWFLG DB 'A' ;ANSWER MODE DISCFLG DB 'D' ;DISCONNECT WHEN DONE ECHOFLG DB 'E' ;TO ECHO AFTER XFER ORIGFLG DB 'ORINT OF MSG ; ;THE CALL TO ILPRT IS FOLLOWED BY A MESSAGE, ;BINARY 0 AS THE END. BINARY 1 MAY BE USED TO ;PAUSE (MESSAGE 'PRESS RETURN TO CONTINUE') ; ILPRT XTHL ;SAVE HL, GET HL=MSG ; ILPLP MOV A,M ;GET CHAR ORA A ;END OF MSG? JZ ILPRET ;..YROR DB ': INVALID OPTION ON MODEM ' DB 'COMMAND - ',CR,LF DB 'PRESS RETURN FOR HELP, CTL-C IF NOT',CR,LF,1,0 ; HELP CALL ILPRT DB 'Format for command is:',cr,lf,cr,lf DB 'MODEM # FILENAME',CR,LF,CR,LF DB 'Where # is a 1 character primary optiER DS 60 ;STACK AREA STACK DS 2 ;STACK POINTER NUMBUF DS 15 ;BUFFER TO HOLD PHONE NUMBER FOR DIALING ; ;16 SECTOR DISK BUFFER (OVERLAYS HELP MSGS) ; DBUF EQU $ ;16 SECTOR DISK BUFFER ; ;INVALID COMMAND ; BADOPT CALL TYPE CALL ILPRT ;EXIT W/ER ;NO REGISTERS SAVED. ; PRTMSG MVI C,PRINT ;GET BDOS FNC JMP BDOS ;PRINT MESSAGE, RETURN ; ;----> ERXIT: EXIT PRINTING MSG FOLLOWING CALL ; ERXIT POP D ;GET MESSAGE CALL PRTMSG ;PRINT IT CALL CKDIS ;DISCONNECT? ; EXIT LHLD STACK ;GET ORIGINA DB ' A answer mode',cr,lf DB ' O originate mode',cr,lf DB ' D disconnect after execution',cr,lf DB ' T go to terminal mode after file xfer',cr,lf DB ' E go to echo mode after file xfer',cr,lf DB ' Q quiet mode - no status msgs',cr,lf DB ' R s' ;ORIGINATE MODE QFLG DB 'Q' ;QUIET TRANSFER (NO MSGS) RSEEFLG DB 'R' ;SEE WHAT'S RECEIVED SSEEFLG DB 'S' ;SEE WHAT'S SENT TERMFLG DB 'T' ;TO TERM AFTER XFER VSEEFLG DB 'V' ;VIEW MESSAGES (NO HDR, ETC) OPTBE EQU $ ;END OF OPTIONS ; RCVSNO DB 0 ;SEES, RETURN CPI 1 ;PAUSE? JZ ILPAUSE ;..YES CALL CTYPE ;TYPE THE MSG ; ILPNEXT INX H ;TO NEXT CHAR JMP ILPLP ;LOOP ; ;PAUSE WHILE TYPING HELP SO INFO DOESN'T ; SCROLL OFF OF VIDEO SCREENS ; ILPAUSE CALL ILPRT ;PRINT: DB CR,LF,'PRESS RETURN on,',cr,lf DB ' which may be followed by sub-options,',cr,lf DB ' and by ".xxx" to set baud rate to xxx' DB cr,lf,cr,lf,1 DB 'Primary Options:',cr,lf DB ' S to send a file',cr,lf DB ' R to receive a file',cr,lf DB ' T to act as a terminal',crR B ;MORE? JNZ MOVE ;..YES, LOOP RET ;..NO, RETURN ; ---------------- OPTION DB 0 ;PRIMARY OPTION ; ;DATAFLG IS USED BY THE "V" SUBCOMMAND - ;IT IS 0 WHEN A HEADER OR CKSUM IS BEING ;SENT/RCD, AND 1 IF "VIEWABLE" DATA (THE ;SECTOR ITSELF) IS ;L STACK SPHL ;RESTORE IT RET ;--EXIT-- TO CP/M ; ;MOVE 128 CHARACTERS ; MOVE128 MVI B,128 ;SET MOVE COUNT ; ;MOVE FROM (HL) TO (DE) LENGTH IN (B) ; MOVE MOV A,M ;GET A CHAR STAX D ;STORE IT INX H ;TO NEXT "FROM" INX D ;TO NEXT "TO" DCfn.ft',cr,lf DB 'Send another file:',CR,LF DB ' MODEM S fn.ft',cr,lf DB 'Then send a third file at 110 baud and disconnect:' DB CR,LF,' MODEM SD.110 fn.ft',cr,lf DB 'Act as a terminal, originate mode, at 110 baud:',cr,lf DB ' MODEM TO.110',CR,Lain the wildcards "*" and "?". ; ; ; ; Please forward all comments, suggestions and improvements to: ; Bruce R. Ratoff ; 80 Gill Lane, Apt 1B ; Iselin, New Jersey 08830 ; ; ; bdos equ 5 ;cp/m entry point exit equ 0 ;cp/m exit point dfcb equ uest on MINICBBS. >!= Operator is available, enter CTL-C to exit CHAT Please go ahead:  ʵ ځO:<2?ʵ:ځx  2Á:=2 ÁN#~*5 WRITE EQU 21 ;0=OK, 1=ERR, 2=?, 0FFH=NO DIR SPC MAKE EQU 22 ;0FFH=BAD REN EQU 23 ;0FFH=BAD STDMA EQU 26 ;SET DMA BDOS EQU BASE+5 REIPL EQU BASE FCB EQU BASE+5CH ;SYSTEM FCB FCBEXT EQU FCB+12 ;FILE EXTENT FCBSNO EQU FCB+32 ;SECTOR # FCB2 EQU BASd by the XMODEM program to indicate that a file may not ; be transmitted. The anticipated purpose is to allow remote use of ; licensed programs withou the danger of their being copied by the ; remote users. This should protect the licensee from liabiF DB ' (Use ctl-D to disconnect)',cr,lf DB 'Receive file, answer mode, view it, 110 baud:',cr,lf DB ' MODEM RAV.110 fn.ft',cr,lf DB 'Autodial a number, and connect at .110 baud ',cr,lf DB ' (300 baud is default)',CR,LF DB ' MODEM C.110',CR,LF,E+6CH ;SECOND FCB END ASE+5 REIPL EQU BASE FCB EQU BASE+5CH ;SYSTEM FCB FCBEXT EQU FCB+12 ;FILE EXTENT FCBSNO EQU FCB+32 ;SECTOR # FCB2 EQU BASlities ; associated with dissemination of licensed software. ; ; To Set the "no copy" flag on a file, type: ; A>TAG d:filename.typ S ; To Reset the flag (allows copying via XMODEM), type: ; A>TAG d:filename.typ R ; ; The filename.typ may cont!9"515*""" CHAT ver 1.5 - Remote conversation utility. Program returns to system in 30 seconds if operator is unavailable. Alerting operator now . . :=2¯ Sorry, no operator available - Please leave your req0 JMP EXIT ; ; BDOS EQUATES (VERSION 2) ; RDCON EQU 1 WRCON EQU 2 PRINT EQU 9 CONST EQU 11 ;CONSOLE STAT OPEN EQU 15 ;0FFH=NOT FOUND CLOSE EQU 16 ; " " SRCHF EQU 17 ; " " SRCHN EQU 18 ; " " ERASE EQU 19 ;NO RET CODE READ EQU 20 ;0=OK, 1=EOF ; title 'TAG - set or reset and display the "no copy" flag on a file' ; by Bruce R. Ratoff - first version 5/18/80 ; modified 5/19/80 by BRR to display 4 across ; ; ; The purpose of this program is to set or reset the f1' bit on a file. ; This is use5ch ;cp/m default fcb dbuff equ 80h ;default disk buffer ; pchar equ 2 ;print character function pmessg equ 9 ;print message function seldsk equ 14 ;select drive function srchfst equ 17 ;search for first file match srchnxt equ 18 ;search for ; filetable equ $ ;start table here, take all avail memory ; end dex to file table ret ; ; ; ; filcnt: ds 1 ;count of files in filetable sropt: ds 1 ;storage for S or R option letter 2 ;get extent # push psw ;save it adi '0' ;convert to ascii mov e,a mvi c,pchar pop psw ora a ;print extent if nonzero jnz pext mvi e,' ' pext: call bdos lda sropt ;get S or R cpi ' ' ;display only? jz nextfile rrc ;bit 7pt: lxi d,ilgopt mvi c,pmessg ;bitch about illegal option call bdos jmp exit ilgopt: db 'Invalid option letter$' okopt: sub a ;zero out file count sta filcnt lxi d,dfcb ;find the first file and get its block map mvi c,srchfst call b0,'$' ; ; ; subroutine to do block moves blkmov: mov a,m ;copy byte from m(hl) to m(de) stax d inx h ;bump pointers inx d dcr b ;loop for count in b jnz blkmov ret ; ; ; subroutine to index bc by file counter filepoint: lhld filcther one...go save it ; ; end of directory encountered, now process them ; tagfile: lxi b,filetable-32 ;allow for filcnt one greater than desired call filepoint push h lxi d,dfcb ;copy next name to default fcb mvi b,32 call blkmov sub a next file match attrib equ 30 ;set file attributes function ; ; org 100h begin: lhld bdos+1 ;set up a stack sphl ;at top of tpa lda dfcb ;check for specific drive dcr a mov e,a ;set up for select disk call mvi c,seldsk inr a ;if trib ;do set attributes call call bdos nextfile: lda dfcb+1 ;get f1 rlc ;isolate f1' ani 1 adi 'R' ;make an R or S sta donmsg+1 lxi d,donmsg mvi c,pmessg ;print completion message for this file call bdos lda filcnt ;get file count=0 for R, 1 for S ani 80h mov b,a ;save mask lxi d,dfcb+1 ;point to f1 ldax d ;get it ani 7fh ;strip f1' ora b ;set bit if option was S stax d ;put it back dcx d ;point to start of fcb sub a ;zap out drive field stax d mvi c,atdos inr a ;search successful? jnz gotfile ;yes, go process rest lxi d,nofile mvi c,pmessg ;say "no file" call bdos jmp exit nofile: db 'File not found$' gotfile: dcr a ;compensate for inr above rrc ;file offset to bits 5 and 6 rrnt ;get file counter mvi h,0 ;force hi ord to 0 dad h ;multiply by 32 dad h dad h dad h dad h dad b ;use as index to file table ret ; ; ; ; filcnt: ds 1 ;count of files in filetable sropt: ds 1 ;storage for S or R option letter sta dfcb ;clear drive number lxi d,-20 ;point back to extent field dad d mvi m,'$' ;tag end of print here pop d ;get back pointer to start of entry inx d ;bump fwd to name mvi c,pmessg call bdos ;say what we're working on lda dfcb+1no specified drive, skip call cnz bdos sub a ;now zap out drive spec sta dfcb mvi a,'?' ;force extent number wild sta dfcb+12 lda dfcb+17 ;get "S" or "R" option sta sropt cpi 'S' jz okopt cpi 'R' jz okopt cpi ' ' jz okopt badoer ani 3 ;multiple of 4? lxi d,crlf mvi c,9 ;if so, time for new line cz bdos lxi h,filcnt ;point to file counter dcr m ;count it down jz exit ;exit if done jmp tagfile ;and go work on next one donmsg: db ' ',9,'$' crlf: db 13,1 inr a sta filcnt ;bump file count pop h ;hl points to directory entry mvi b,32 call blkmov ;copy entry into table mvi c,srchnxt ;search for another entry lxi d,dfcb call bdos inr a ;returns 0ffh at end of search jnz gotfile ;got anoc rrc ani 60h lxi h,dbuff ;point to base of buffer mov c,a mvi b,0 dad b ;index by file offset push h ;save for the moment lxi b,filetable call filepoint ;get table pointer to hl xchg ;de now points to place in table lda filcnt !9"x1x  APXMODEM ver 4.1 :]::SʉR++INVALID OPTION ON XMODEM COMMAND++ Must be S for SEND or R for RECEIVE $oͭ%PYڶ%27͙͆ͧͬڤ×>ͦͬڶ"o!e>C)#>O)#>M)++CAN'T RECEIVE A .COM FILE++ "MODEM R" and the filename.filetype that you want it saved under on your disk. It should look like this on your console (naturally you are running the CP/M operating system): A>MODEM R CROSSREF.ASM For additional command options and combinations,, etc.) which are available from the CP/M users group, from any number of other systems up around the country such as this, or from this system (we ordinarily keep it on drive A and call it "MODEM???.ASM", the "?'s" rep- resenting the latest version n> ͦXMODEM PROGRAM CANCELLED $:6<26\<++FILE EXISTS - USE A DIFFERENT NAME++ $2h2|\<++ERROR - CAN'T MAKE FILE++ Directory must be full $>?2h>22\<++FILE NOT FOUND++$\<:2o&T:3_)))))))"3= on our system. Wait until you see this system respond with: FILE OPEN, SIZE: (XXXX) SECTORS Now the system is waiting for an acknowledgement from your MODEM.COM program that it (your MODEM. COM) is ready to receive the file. At this point you 0~# *x~#)zO͚:ˆ" xžO::Ćé2U!l\)2|2h_ Rename filetype ".OBJ" and try again $-c FILE OPEN - READY TO RECEIVE c%̀Q̀"!]~ ˜++NO FILE NAME SPECIFIED++ $ ~?ʦ#š++CAN'T USE WILD CARD OPTIONS $27 U*-7U>ͦ:7<27 s to the logged in drive, and we assume for purposes of this example that you are logged in on drive A; that is, you have not changed to drive B since the system answered the phone). (Note: Transferring files from drive B is discussed further on.) umber indentifiers.) TO SEND A FILE FROM THIS SYSTEM TO YOURS Type "XMODEM S" filename.filetype. The file you want to receive (send from this system to yours) must be on the A drive (no drive specified in the XMODEM command chain means it default!oF+++:2x23~222h2|\" prompt on your screen. Now you set up your MODEM.COM pro- gram to receive the file from this system by typing FILE TRANSFERS TO AND FROM THIS SYSTEM USING "XMODEM.COM" You must have a copy of a program called MODEM.COM installed on your system. This would be the object code of one of the versions of Ward Christensen's MODEM.ASM (MODEM527.ASM, MODEM???.ASM++UNABLE TO RECEIVE BLOCK - ABORTING++ $U*WU*/Fz25!U*w,OQU*:5G:6z<̀>ͦ>ͦ:6ͦ:6/ͦ!~ͦ,žyͦ O:7<27 ++CAN'T SEND SECTOR - ABORTING++ $÷1xU>ͦU Thus, if you want to receive on your system the file called "CROSSREF.ASM", it should look like this on the screen: A>XMODEM S CROSSREF.ASM You should check to make sure we have "XMODEM.COM" on drive A. This command is typed by you to execute \+! 2;!z"9"ͦ++ERROR WRITING FILE++ $::P:|YYV:Ć7:O͚:ˆ" xžO::Ćé2U!l\)2|2h_RS \<++CAN'T CLOSE FILE++ $ 3 |*{0|}:;=2;p*9'"9:87z\ʮ=ʽ++FILE READ ERROR++ $! y|>28y2;!z"9Y*9!'"9:;<2;:;Oz such as viewing an ascii file as it is being trans- ferred, refer to the MODEM.DOC file on drive A. To send a file from drive B of this system to your system, you must declare the B drive in the command line of this system's "XMODEM.COM" program, atransfer and return to the CP/M command mode. Please do not attempt to send a CP/M .COM file. This system's "XMODEM.COM" program will abort the transfer and return to the CP/M command mode. If you want to send a CP/M .COM file, we suggest you use mmand line of your MODEM.COM program when you bring it up at your end in local mode to either receive or send a file, IF YOU LOGGED INTO THIS SYSTEM AT A BAUDRATE OTHER THAN 300 BAUD. It is also necessary for you to declare in your MODEM.COM command nd a file called "MYPROG.ASM", this system's command line should look like this: A>XMODEM R MYPROG.ASM The name of the file that this system is to receive does not have to be same as the name of the file you are sending. The name you declare is: A>XMODEM S B:CROSSREF.ASM WHEN USING XMODEM.COM, IT IS NOT NECESSARY TO DECLARE ANY OTHER PARAMETRS IN THE COMMAND LINE SUCH AS THE BAUDRATE, "Q" FOR QUIET MODE, OR ANSWER/ORIGINATE MODE DECLARATION. XMODEM.COM has been constructed to de- fauM some comments (documentation) about what it is, what it does, and how to do it. Thanks. -------------------- CHICAGO RAPthe CP/M filetype ".OBJ" when declaring the filename at this end. If you do send us a CP/M .COM file, please also send us some comments (documentation) about what it is, what it does, and how to do it. Thanks. -------------------- CHICAGO RAPline (at your end in local mode) the A option (i.e., MODEM RA filename.type) if you have used the FLIP function to reverse modes (put this sys- tem in originate mode and bring up yours in answer). For example, if you are sending a file from this systn the command line of this system's "XMODEM.COM" program will be written on this system's disk only. Please do not use a filename.filetype for a file you are sending that already exists on the A drive disk. This system's "XMODEM.COM" will abort the lt to the logged in baudrate and mode, and XMODEM is always in the quiet (Q) mode, so IT IS NOT NECESS- ARY TO DECLARE THESE OPTIONS IN THE XMODEM COMMAND LINE. It is necessary, however, to declare the baudrate (as detailed in "MODEM.DOC") in the coould look like this: MODEM RA.600 PUT.ASM -------------------- TO SEND A FILE TO THIS SYSTEM: Type "XMODEM R" filename.filetype, then go into your system's local mode and type "MODEM S" filename.file- type. For example, if you want to seem to yours, and you logged in at 600 baud, and then exe- cuted the FLIP function (to improve reception at your end), and you are sending yourself the file PUT.ASM, your command line when bringing up your MODEM.COM in local mode to receive the file sh