This file is a text archive of the files for Tandy Model 4 Kermit. Each file begins with a line <<< name >>>, where "name" is the name of the file. The files begin on the next line. <<< m4boo.bas >>> 10 INPUT "Input filename";INFILE$ 20 INPUT "Output filename (/CMD file)";OUTFILE$ 30 OPEN "I",1,INFILE$:OPEN "O",2,OUTFILE$ 40 WHILE (EOF(1)=0) 50 INPUT #1,A$:IF INSTR(A$,"*****")<>0 THEN 150 60 FOR T=1 TO LEN(A$) STEP 2: B=VAL("&h"+MID$(A$,T,2)) 70 SUM=(SUM+B) AND -4097 80 PRINT #2,CHR$(B); 90 NEXT T 100 WEND 110 PRINT "Error: Early End-Of-File Encountered!" 120 PRINT "Last record read:" 130 PRINT A$ 140 CLOSE: END 150 I=INSTR(A$," ")+1:J=INSTR(I,A$," ")-I:NEWSUM=VAL(MID$(A$,I,J)) 160 IF NEWSUM=SUM THEN PRINT "Checksum OK:";NEWSUM;"=";SUM: GOTO 180 170 PRINT "Bad checksum:";NEWSUM;"<>";SUM 180 CLOSE: END <<< m4h19.equ >>> *LIST OFF ;********* ; TRSDOS/LDOS 6.x Supervisor Call Equate File ; (c) 1983 Mark Vasoll - All rights reserved ; Licensed to Softronics Computer Systems ;********* @ABORT EQU 015H @ADTSK EQU 01DH @BANK EQU 066H @BKSP EQU 03DH @BREAK EQU 067H @CHNIO EQU 014H @CKDRV EQU 021H @CKEOF EQU 03EH @CKTSK EQU 01CH @CLOSE EQU 03CH @CMNDI EQU 018H @CMNDR EQU 019H @CTL EQU 005H @DATE EQU 012H @DCINIT EQU 02AH @DCRES EQU 02BH @DCSTAT EQU 028H @DEBUG EQU 01BH @DECHEX EQU 060H @DIRRD EQU 057H @DIRWR EQU 058H @DIV8 EQU 05DH @DIV16 EQU 05EH @DODIR EQU 022H @DSP EQU 002H @DSPLY EQU 00AH @ERROR EQU 01AH @EXIT EQU 016H @FEXT EQU 04FH @FLAGS EQU 065H @FNAME EQU 050H @FSPEC EQU 04EH @GET EQU 003H @GTDCB EQU 052H @GTDCT EQU 051H @GTMOD EQU 053H @HDFMT EQU 034H @HEXDEC EQU 061H @HEX8 EQU 062H @HEX16 EQU 063H @HIGH$ EQU 064H @INIT EQU 03AH @IPL EQU 000H @KBD EQU 008H @KEY EQU 001H @KEYIN EQU 009H @KLTSK EQU 020H @LOAD EQU 04CH @LOC EQU 03FH @LOF EQU 040H @LOGER EQU 00BH @LOGOT EQU 00CH @MSG EQU 00DH @MUL8 EQU 05AH @MUL16 EQU 05BH @OPEN EQU 03BH @PARAM EQU 011H @PAUSE EQU 010H @PEOF EQU 041H @POSN EQU 042H @PRINT EQU 00EH @PRT EQU 006H @PUT EQU 004H @RAMDIR EQU 023H @RDHDR EQU 030H @RDSEC EQU 031H @RDSSC EQU 055H @RDTRK EQU 033H @READ EQU 043H @REMOV EQU 039H @RENAM EQU 038H @REW EQU 044H @RMTSK EQU 01EH @RPTSK EQU 01FH @RREAD EQU 045H @RSLCT EQU 02FH @RSTOR EQU 02CH @RUN EQU 04DH @RWRIT EQU 046H @SEEK EQU 02EH @SEEKSC EQU 047H @SKIP EQU 048H @SLCT EQU 029H @SOUND EQU 068H @STEPI EQU 02DH @TIME EQU 013H @VDCTL EQU 00FH @VER EQU 049H @VRSEC EQU 032H @WEOF EQU 04AH @WHERE EQU 007H @WRITE EQU 04BH @WRSEC EQU 035H @WRSSC EQU 036H @WRTRK EQU 037H AFLAG$ EQU 0 CFLAG$ EQU 2 DFLAG$ EQU 3 EFLAG$ EQU 4 FEMSK$ EQU 5 IFLAG$ EQU 8 KFLAG$ EQU 10 MODOUT EQU 12 NFLAG$ EQU 13 OPREG$ EQU 14 RFLAG$ EQU 17 SFLAG$ EQU 18 TFLAG$ EQU 19 UFLAG$ EQU 20 VFLAG$ EQU 21 WRINTMASK$ EQU 22 SVCTABPTR EQU 26 VERSIONBYTE EQU 27 ICNFGVECTOR EQU 28 KITSKVECTOR EQU 31 ;********* ; End of Equate File ;********* *LIST ON <<< m4h19.hex >>> 050648313920202001020030181D000006244845415448000000005F5F14007D00000000000000 000029002803C336363E65EF79E67F4F3264372A07377CB52808E5210000220737C979FE1BCA50 31FE20DA4E30CD5936C341363A6437874F0600216630095E2356EB7CB53A6437CA4136E9000000 0000000000000000000000A630D030D5300631000018313E310000000000000000000000000000 000000000000000000000000000000000000000000003A1230B7CA47323A11306FED5B13303E01 D390424B0B78B120FBAFD390424B0B78B120FB2D20E8C341363E18C3D831C50604F53E0FEFF1C1 3E4F95FE08D2F0303E1DCD31363E1AC331367DC608E6F86FC5D5E50603F53E0FEFF101020031E1 D1C1C341363E1ACDD8313A1C30E6023E1DC4D831C34136210000C5D5E50603F53E0FEFF1E1D1C1 C3AE33210000C5D5E50603F53E0FEFF1E1D1C1C341363E1DCDD8313A1C30E6013E1AC4D831C341 36217431220737C341364142434445464748494A4B4C4D4E4F594066717078796A6B626F6C3A64 37215931061B11A0314EB9280E23131310F7210000220737C34136EB5E2356210000220737EB3A 6437E9D6310631DE31D0301831E331E6312B31E931AE33223483357F353D3482349B3489344732 913496349B349B349132B33205335733D8323E1B326437C32E363E19C3D831C34136C34136C506 04F53E0FEFF1C17CB7C2D6313E0FCD31363E17212F01020032FF117FFF015000F5F5F3FD7E0EE6 FED384F1EDB8F5FD7E0EF601D384FBF1F13D20E2111337D5D5E1133620014F00EDB02600D1C5E5 D506090E00F53E0FEFF1D1E1C13E0EC331363E10CD31360E00C52600111337C5E5D506090E01F5 3E0FEFF1D1E1C1E5626B06507EEE80772310F9E1C5E5D506090E00F53E0FEFF1D1E1C1247CFE18 20CCFBC1790CB728C23E11C3D831ED5BF136C50604F53E0FEFF1C1EBE5010737B7ED42E1280773 23722322F136C341362AF13601F336B7E5ED42E128152B562B5E22F136EBC5D5E50603F53E0FEF F1E1D1C1C34136C50604F53E0FEFF1C1E52E00C5D5E50603F53E0FEFF1E1D1C1CD2234E1C5D5E5 0603F53E0FEFF1E101020033D1C1C34136C50604F53E0FEFF1C1CDBB361100F8B7ED52444D78B1 28372100F81101F8F5F3FD7E0EE6FED384F13620F5FD7E0EF601D384FBF10B78B12816F5F3FD7E 0EE6FED384F1EDB0F5FD7E0EF601D384FBF1C34136C50604F53E0FEFF1C1E5CDBB36EBE12E00CD BB36EBB7D5ED52444D78B12835E1545D13F5F3FD7E0EE6FED384F13620F5FD7E0EF601D384FBF1 0B78B12816F5F3FD7E0EE6FED384F1EDB0F5FD7E0EF601D384FBF1C34136C50604F53E0FEFF1C1 CDBB36E5E5C1217FFFB7ED42E5C1E12857E5D113C5D5E53E0FCD3136E1D1C1F5F3FD7E0EE6FED3 84F13620F5FD7E0EF601D384FBF13E1EF5F3FD7E0EE6FED384F1F578B12812F1EDA0010200343D 20F5F5FD7E0EF601D384FBF118DDF1F5FD7E0EF601D384FBF13E0EC33136C34136C50604F53E0F EFF1C1E5CDBB36E32E4FCDBB36C1C579BD28E41883111337D5C50604F53E0FEFF1C1E5C5E5D506 090E01F53E0FEFF1D1E1C13E4F95260019E5D1B728064F060023EDB03E2012E1D1C5E5D506090E 00F53E0FEFF1D1E1C1C34136AF320937C341363E01320937C341363E11C3D8313E10C3D83121CE 342207373A6437320B37C34136FD34FD34FD3428353F35FD34FD3400350A35FD34FD34FD343A35 3535FD34FD3414351E353A0B37FE782808FE79206B0E1218020E003A6437D631FE09D24136FE00 DA4136CB27814F060021AA34095E2356D5C9C34136010200353A1C30F601321C3018F33A1C30F6 02321C3018E93A1C30E6FE321C3018DF3A1C30E6FD321C3018D52A0C377CB5CA4136114136D5E9 3E0FC3D8312A0E3718EC3E0EC3D8313A6437D620DA4136FE18D24136321237215D35220737C341 363A6437D620DA4136FE50D241366F3A123767C5D5E50603F53E0FEFF1E1D1C1C341363E011801 AF320A37C50604F53E0FEFF1C13E1794286BFDE5E5C5D5F53E0FCD3136F1D1C1E1FDE13A0A37B7 282DE52E00CDBB36F1E5D101500009F5F3FD7E0EE6FED384F1C5EDB0C1F5FD7E0EF601D384FBF1 3CFE1720E36718303E1794212FFF117FFF015000F5F3FD7E0EE6FED384F1C5EDB8C1F5FD7E0EF6 01D384FBF13D20E501F50036C50604F53E0FEFF1C1E5111337D5D5E113014F003620EDB0D1E1C5 E5D506090E00F53E0FEFF1D1E1C13E0EC331363A64374F0602B7BFDDE5DD2A0B303E14EFDDE13A 6437BFC9210000C5D5E50603F53E0FEFF1E1D1C1C3AE33F5C50604F53E0FEFF1C1E53A0937B728 38111337C5E5D506090E01F53E0FEFF1D1E1C13E4F954F0600B7281D2E4F260019D55D542BEDB8 D1E1C5E5D506090E00F53E0FEFF1D1E1C1E5E1F1C32E3606083A0F304F3E0FEFC906083A10304F 3E0FEFC9C5F5D5E5D12100F801500015FACD360918F9160019D1F1C1C9C5F5D50100F8B7ED4216 00015000B7ED42DAEB361418F70962D1F1C1C9F336010E07370000000000A736B136000000016D 64370048313920456D756C61746F722D66696C74657220666F7220545253444F5320362E322E20 5772697474656E2062793A2020477265676720576F6E6465726C791D1A4C6F6164206164647265 73733A2003202020202020202020456E64696E6720616464726573733A200301021F380000ED53 0B303E65EFFD2210372165373E0AEF21000006003E64EF221530220230E521FEF3C1B7E5ED42E1 3802C5E123016507B7ED42E52B22173006003E64EFD1ED531F3821CF37E53E63EF3603E13E0AEF 2A1F38010030B7E5ED42221A30E101650709E521B5373E0AEFD121CF37E53E63EF360DE13E0AEF DD21EB38ED4B1A30DD6E00DD23DD6600DD23DDE5E5DDE1DD6E00DD660109DD7500DD7401C1C5DD E121693AB7ED4220D4016507ED5B1F38210030EDB0DD2A0B30ED5B1F38DD360047DD7301DD7202 210000BFC9CC3122302C302F303A304130463049304C304F305630603063307430763078307A30 7E308030A730AB30AE30B330CE30D330E43001021F39CE31E930EE300431093129313C31413151 3154315731753178317D318C318F3199319D31A031A231A431A631A831AA31AC31AE31B031B231 B431B631B831BA31BC31BE31C031C231C431C631C831CA31D931DC31E131E431E731F531233245 3252328F32B8331D343E348034843487348C348F34943499349C349F34A234A534A834CF342935 2E3531353B3545354A354F355235553558355B355E35633568356C357D358535A735B0350B362C 362F363A3665366B36A536AA36B436C836E6360C370E3742365736FA314A329E35E0340C319332 A132AE32B132B432B732C532D632F136D031D231D431F23203330F33553362336933AC33383542 35AA34AC34014C1F3AAE34B034B234B434B634B834BA34BC34BE34C034C234C434C634C834CA34 CC34EC34F534FE3444314B314E3113311631013506350B35103515351A351F352435E7342D3433 34D13320340202213800000000000000000000000000000000 ***** 768 ***** <<< m4h19.mac >>> ; m4h19/mac *LIST OFF SWAP_IN MACRO PUSH AF DI LD A,(IY+SCR_MASK) AND S_IN OUT (132),A POP AF ENDM ; SWAP_OUT MACRO PUSH AF LD A,(IY+SCR_MASK) OR S_OUT OUT (132),A EI POP AF ENDM ; SVC MACRO #P1 PUSH AF LD A,#P1 RST 28H POP AF ENDM ; SSVC MACRO #P1 LD A,#P1 RST 28H ENDM ; GET_CURSOR MACRO PUSH BC LD B,4 SVC @VDCTL POP BC ENDM ; PUT_CURSOR MACRO PUSH BC PUSH DE PUSH HL LD B,3 SVC @VDCTL POP HL POP DE POP BC ENDM ; GET_LINE MACRO PUSH BC PUSH HL PUSH DE LD B,9 LD C,1 SVC @VDCTL POP DE POP HL POP BC ENDM ; PUT_LINE MACRO PUSH BC PUSH HL PUSH DE LD B,9 LD C,0 SVC @VDCTL POP DE POP HL POP BC ENDM ; *LIST ON <<< m4h19s.hex >>> 05065345544831390102002511B32901FF00ED53AF29EDB01100273E53EFC2E726E5DDE111C92A 2AAF297EFE0DCA3B26FE2828032318F32B3E11EFC23B263AD02AB72811E660C2D5262A58297CB7 C2CD267DDD770F3ADA2AB72811E660C2D5262A56297CB7C2CD267DDD77103AE42AB72849E6A0C2 D52606002100003E64EFC2DF26DD7E174FDD7E1847B7ED42C2C426DD7E156FDD7E166706003E64 EFC2DF262168293E19EF2172293E19EF217C293E19EF2187293E19EFC337263AF12AB7280EE660 C2D5262A5E29DD7513DD74143AFD2AB72811E660C2D5262A5C297CB7C2CD267DDD77113A052BB7 CAEC25E6A0C2D5263A6029DD77123A1F2BB7CA0D26E6A0C2D526DD4E1DDD461EDDE501020026E1 090EFF3A6629B728020E7F713A0D2BB7280CE6A0C2D5263A6229B7C43B263A152BB72812E6A0C2 D5263A6429B7CA372621C2273E0AEF210000C92178273E0AEFDD6E102600CDAD262188273E0AEF DD6E0F2600CDAD260E0D3E02EF21B4273E0AEF21BB27DD7E12B7200321BE273E0AEF2199273E0A EFDD6E112600CDAD2621A6273E0AEFDD6E13DD6614CDAD262124273E0AEFDD4E1DDD461EDDE5E1 097E213527FEFF20032139273E0AEFC911B52AD53E61EFEB3603E13E20BE20032318FA3E0AEFC9 2107273E0AEFC39425216827DD213C27DD2154273E0AEF21FFFFC9F6C04F3E1AEF18F43AB129B7 20E43C32B1292195293E19EF21A1293E19EFC30C25010200272448454154480043616E206E6F74 207265636C61696D2075736564206D656D6F7279210D0A537472697020387468206269743A2003 5945530D4E4F0D43616E206E6F742066696E64204831392066696C7465720D4261642070617261 6D657465722076616C75650D56616C756520746F6F206C617267650D4E6F726D616C2063757273 6F723A20032C20426C6F636B20637572736F723A20032C204475726174696F6E3A20032C204672 657175656E63793A200342656C6C3A20034F4E034F4646035265636F676E697A65642070617261 6D65746572733A0A435552534F522020202020202D2020204E6F726D616C20637572736F722063 6861726163746572010200280A424C4F434B202020202020202D202020426C6F636B2063757273 6F72206368617261637465720A42454C4C20202020202020202D2020205475726E2062656C6C20 4F4E206F72204F46460A4652455155454E43592020202D2020204672657175656E6379206F6620 62656C6C2028696E7665727365206F66207265616C2066726571290A4455524154494F4E202020 202D2020204C656E677468206F6620746F6E652028323535204D4158290A535452495038202020 2020202D20202052656D6F766520387468206269742066726F6D20636861726163746572732028 64656661756C743D4F4E290A52454D4F56452020202020202D20202052656D6F766501B8002920 7468652066696C7465722066726F6D206D656D6F72790A53484F5720202020202020202D202020 53686F7720616C6C2076616C7565730A48454C5020202020202020202D20202054686973206D65 73736167650A0D0000000000000000000000000000000000007265736574202A736F0D72657365 74202A68700D72656D6F7665202A68700D726F757465202A736F202A646F0D736574202A687020 6831390D66696C746572202A736F202A687000000020202020015CC92A8085424C4F434B005829 86435552534F520056294652454D4F5645005A29994652455155454E4359005E29984455524154 494F4E005C294442454C4C0060294453484F570062294448454C50006429465354524950380066 290002020025000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000 ***** 3468 ***** <<< m4ker.src >>> <<< m4add.asm >>> ; m4add/asm ; ; Input a line from a take file ; DOTAKE EQU $ LD HL,CMDBUF ;WHERE TO PUT THE TEXT LD B,0 ;CHARACTER COUNTER CALL CONIN IFA 128,TAKERR ;Jump if break was pressed TAKLOP LD DE,TFCB ;FCB FOR TAKE FILE CALL XGET ;Call @GET svc JR NZ,TAKERR ;QUIT ON AN ERROR LD (HL),A ;SAVE THE CHARACTER INC HL ;POINT TO THE NEXT INC B ;ADD TO CHARACTER COUNT IFA CR,TAK020 ;Go if at the end of string LD C,A LD A,(TAKLOG) ;IS DISPLAY OF TAKE FILES ON? OR A LD A,C CALL NZ,CONOUT JR TAKLOP TAK020 RET ;RETURN WITH THE STRING TAKERR LD DE,TFCB ;GET READY TO CLOSE THE FILE CALL XCLOSE ;Close the file XOR A ;TURN THE TAKE FLAG OFF LD (TAKFLG),A ;RESET IT LD A,29 CALL CONOUT SCF ;SET CARRY FOR A PARSE ERROR RET ; ; This routine is used by the command parser routines to input a ; string from the keyboard. It recognizes the TAKFLG which tells ; it to input a string from the active take file. ; Input to the routine is HL which points to the string buffer, ; and B which has an initial count of the number of characters ; already in the buffer. ; GETSTR LD A,(TAKFLG) ;Is there a TAKE file active OR A JP NZ,DOTAKE ;If so than go fill buffer from file. LD IY,(FLAGS) ;Get the flags address. BIT 5,(IY+18) ;Check if JCL active. JR Z,SKIP_JCL ;Jump if JCL not active. LD HL,CMDBUF ;Get the input buffer. LD BC,5000H ;Set B to max count, and C to zero. JP XKEYIN ;Get a line from JCL and return. ; SKIP_JCL PUSH HL ;Save the registers PUSH DE LD A,B ;Save the number of character already in LD (TEMP4),A ;the buffer for later GET010 CALL XKEY ;Get a character from the keyboard JP NZ,GETEXT ;Humm, what do we do on an error IFANOT 8,GET030 ;Go if not backspace LD E,A ;Save the KEY we got LD A,B ;Get the number of characters IFZ GET010 ;Go if no place to backspace over DEC B ;At least one space left DEC HL ;Back up the buffer pointer LD A,E ;Get the character CALL CONOUT ;Display it JR GET010 ;Go get a new key GET030 IFA CR,GET040 ;Go if enter pressed IFANOT 24,GET036 ;Jump if not SHIFT <- GET035 LD A,B ;NUMBER LEFT IFZ GET010 ;Go if all were erased LD A,8 ;BACKSPACE CALL CONOUT ;PRINT IT DEC B ;ONE MORE LEFT DEC HL ;BACKUP IN THE BUFFER JR GET035 ;KEEP LOOPING GET036 IFA ESC,GET040 ;Go if it was escape IFANOT 129,GET038 ;Go if not F1 (Also escape) LD A,ESC ;GET AN ESCAPE JR GET040 ;JOIN THE CODE FOR EXIT GET038 IFA 128,GET040 ;Go it it was a break IFALT 20H,GET010 ;Ignore other control keys GET040 INC B ;ONE LESS CHARACTER LEFT LD (HL),A ;PUT THE CHARACTER IN THE BUFFER JR NZ,GET050 ;WHEN nZ IS SET, NO MORE CHARS LEFT DEC B ;SAY WE STILL HAVE ONE JR GET060 ;MIGHT BE '?' WHICH IS IGNORED AS LAST GET050 IFA CR,GETEXT ;Finish up if CR pressed IFA ESC,GETEXT ;Same for escape IFA 128,GETEXT ;Same for break INC HL ;ONE MORE IN THE BUFFER CALL CONOUT ;PRINT WHAT WAS TYPED GET060 CP '?' ;WAS IT A '?' ? JP NZ,GET010 ;GET A NEW KEY IF NOT LD A,8 ;GET A BACKSPACE CALL CONOUT ;PRINT IT TO REMOVE THE '?' DEC HL ;POINT AT THE '?' PUSH HL ;HL -> IY POP IY LD A,' ' ;LOOK FOR A PREVIOUS SPACE IFA (IY-1),GETEXT ;Look for a previous space LD A,B ;ARE WE AT THE START OF THE LINE DEC A ;IF Z IS SET THAN THE CURSOR IS AT HOME ON THE LINE. NO SPACE WILL ;BE ADDED IN THIS CASE. LD A,' ' ;PUT A SPACE ON THE DISPLAY CALL NZ,CONOUT ;PRINT IT GETEXT LD A,B ;GET NUMBER ON THE LINE DEC A JR NZ,GET110 ;AT LEAST ONE CHAR ON THE LINE PUSH AF ;PUT AF INTO BC POP BC LD A,(HL) ;WAS '?' THE TERMINATOR? CP '?' LD A,B ;GET THE LENGTH IN A JR NZ,GET120 GET110 INC A ;COUNT THE TERMINATOR IF IT IS '?' GET120 LD B,A ;SAVE THE LENGTH LD A,(HL) ;GET THE TERMINATOR IFA ESC,GET130 ;Skip normal return if escape SLA A ;CHECK FOR BREAK (128 IS NEGATIVE) JR C,GET130 ;ALSO GIVES C STATUS LIKE @KEYIN SRL A ;FIX IT BACK OR 10H ;MAKE CR, CHR$(29), '?' IS UNDISTURBED CALL CONOUT ;PRINT THE CHARACTER GET130 POP DE ;RESTORE THE REGS POP HL RET ;RETURN TO THE CALLER ; STDOUT LD A,16 ;REVERSE VIDEO ON JP CONOUT ;USE THE RETURN ON THE STACK STDEND LD A,17 ;REVERSE VIDEO OFF JP CONOUT ;USE THE RETURN ON THE STACK ; ;ENTRY POINT FOR INTERUPT DRIVEN RECEIVE CHARACTER ROUTINE. ; GETINT JR NZ,GTIN10 ;NO CHARACTER AVAILABLE LD HL,(CURCHR) ;CURRENT POS IN BUFFER LD (HL),C ;CHARACTER IS IN C, STORE IT INC L ;POINT TO NEXT WRITE POSITION LD A,(NXTCHR) ;CHECK FOR OVERFLOW IFA L,GTIN10 LD (CURCHR),HL ;SAVE ADDRESS OF NEXT STORE LD A,(MAXCNT) LD E,A LD HL,INCNT ;Get the address of the count INC (HL) ;Add one to the count LD A,(HL) ;Get the count IFALT E,GTIN10 ;Jump if below count LD A,(FLOFLG) ;ARE WE DOING FLOW CONTROL? IFZ GTIN10 ;Go if not doing flow control LD A,C ;GET THE CHARACTER JUST RECEIVED IFA XOFF,GTIN06 ;Jump if XOFF received IFANOT XON,GTIN07 ;Jump if not time for XON XOR A GTIN06 LD (XOFREC),A ;Store the new flag value GTIN07 LD A,(XFFLG) ;SEE IF WE ALREADY SENT IT IFNZ GTIN10 ;Go if XOFF already sent INC A ;MAKE IT NON-ZERO LD (XFFLG),A ;SET IT LD E,XOFF ;Get an XOFF character CALL OUTCHR ;SENT IT OUT GTIN10 RET ; ;LOG THE CHARACTER IN THE LOG FILE ; LOGIT PUSH AF ;Save the character to log LD A,(LOGFLG) ;Check if logging active IFANOT 2,LOGITO ;Go if logging not on, or file not open POP AF ;Get the character back PUSH AF ;Put the character back IFANOT LF,LOGT0 ;Is it LINE FEED? Jump if not LD A,(PREVLCHR) ;Check if previous character was IFA CR,LOGITO ;Throw out if previous was LD A,LF ;Get a line feed character back LOGT0 PUSH DE ;Save the registers LD (PREVLCHR),A ;Save the previous character LD DE,LFCB ;Get the FCB address LOGT1 CALL XPUT ;@PUT the character to the file JR Z,LOGEXT ;Exit if no errors on output LOGT2 CALL XERROR0 ;Print the system message given in A LD DE,LFCB ;Get the FCB back CALL XCLOSE ;Make sure that the file is closed STROUT ERMS20 ;Say that the file was closed XOR A ;Reset the logging flag LD (LOGFLG),A ;Store the new value LOGEXT POP DE ;Restore DE LOGITO POP AF ;Restore the character RET ;Back to caller ; ; These are the TRSDOS 6.x SVC definitions ; XPARAM DOSVC 17 ;@PARAM SVC (Parse ()'d argument list). XFSPEC DOSVC 78 ;@FSPEC SVC (Convert filename to TRSDOS) XINIT DOSVC 58 ;@INIT SVC (Create a file on disk device) XOPEN DOSVC 59 ;@OPEN SVC (Open a file) XREAD DOSVC 67 ;@READ SVC (Read a record) XSKIP DOSVC 72 ;@SKIP SVC (Skip a logical record) XCLOSE DOSVC 60 ;@CLOSE SVC (Close a file) XVER DOSVC 73 ;@VER SVC (Write with verification) XCTL DOSVC 5 ;@CTL SVC, perform control operation XPRT PUSH BC ;Send character to printer PUSH AF LD C,A LD A,6 JR SVCSAV XVDCTL DOSVC 15 ;@VDCTL SVC (Perform video operations) XGET DOSVC 3 ;@GET SVC (Get a character from a file) ; ; SVC'S that require the character passed in A to be in C should ; look like this. ; XPUT PUSH BC ;SAVE BC PUSH AF ;SAVE AF LD C,A LD A,4 ;@PUT SVC SVCSAV RST 28H ;CALL AN SVC POP BC ;POPPING BC DOES NOT AFFECT THE FLAGS LD (XERRNO),A ;Store last error number LD A,B ;B HAS OLD A SO RESTORE POP BC ;GET OLD BC RET ;RETURN TO THE CALLER XKEYIN DOSVC 9 ;Get a string from *DO (@KEYIN SVC) XHIGH DOSVC 100 ;@HIGH$ SVC XLOAD DOSVC 76 ;@LOAD SVC (Load an executable) XCHKDRV DOSVC 33 ;@CHKDRV SVC (Check if drive is ready) XTIME DOSVC 19 ;@TIME SVC (Get current system time) XADTSK DOSVC 29 ;@ADTSK SVC (Add a task to the table) XCKTSK DOSVC 28 ;@CKTSK SVC (Check if task slot available) XRMTSK DOSVC 30 ;@RMTSK SVC (Remove task from table) XKLTSK DOSVC 32 ;@KLTSK SVC (Kill current exec task) XPAUSE DOSVC 16 ;@PAUSE SVC (Delay for count in BC) XFLAGS DOSVC 101 ;@FLAGS SVC (Get system flags address) XREMOVE DOSVC 57 ;@REMOV SVC (Remove opened file) XKILL EQU XREMOVE XDECHEX DOSVC 96 ;@DECHEX SVC (Convert ASCII to binary) XHEXDEC DOSVC 97 ;@HEXDEC SVC (Convert binary to ASCII) XKBD DOSVC 8 ;@KBD SVC (Get a keyboard char, no wait) XKEY DOSVC 1 ;@KEY SVC (Get a keyboard char, wait) XCMNDR DOSVC 25 ;@CMNDR SVC (Execute system command) XMUL16 DOSVC 91 ;@MUL16 SVC (Multiply 8 bit by 16 bi&t) XDSP PUSH BC ;SAVE BC PUSH AF ;SAVE AF LD C,A LD A,2 ;@DSP SVC JP SVCSAV XGTDCB DOSVC 82 ;@GTDCB SVC (Get the DCB for given device) XEXIT LD L,A ;A HAS OUR RETURN CODE LD H,0 ;MAKE HL THE RETURN CODE DOSVC 22 ;Do @EXIT SVC XERROR0 LD A,0 ;Get the last error number XERRNO EQU $-1 XERROR PUSH BC ;SAVE BC AND AF PUSH AF LD IY,(FLAGS) ;GET @FLAGS ADDRESS RES 6,(IY+2) ;RESET ALL SPECIAL BITS RES 7,(IY+2) RES 6,(IY+18) OR 0C0H ;MAKE SIMPLE MESSAGES LD C,A ;C NEEDS THE ERROR NUMBER CALL NEWLIN ;Get a new line for the messages LD A,26 ;@ERROR SVC (ISSUE A SYSTEM MESSAGE) JP SVCSAV ;GO CALL IT ; ; Set up interrupt and device information ; SETINT EQU $ ; ; This code sets up the interrupt driven receiver. It calls @CTL ; to pass the address of the "GETINT" routine, which is called ; each time a character is received by the UART ; LD IY,GETINT ;Where to transfer control to LD DE,(CLDCB) ;Which device to get LD C,4 ;Ctl function 4 CALL XCTL ;Do @CTL ; ; Install *FO and *FI devices ; LD DE,0 ;Find a new DCB for this device CALL XGTDCB JR NZ,NODCB ;Abort if an error occured LD (FOTDCB),HL ;Save the pointer to the DCB PUSH HL ;Move it to IX to do indexing POP IX LD (IX+6),'F' ;Store the name in the DCB LD (IX+7),'O' LD A,2 ;Select @PUT capabilities only LD (IX),A LD HL,FILOUT ;Get the entry point LD (IX+1),L ;Store it LD (IX+2),H LD DE,0 ;Get a new DCB for the input device CALL XGTDCB JR NZ,NODCB ;Abort if an error occurs LD (FINDCB),HL ;Save the address of the DCB PUSH HL ;Put the address in IX for indexing POP IX LD (IX+6),'F' ;Store the device name in the DCB LD (IX+7),'I' LD A,1 ;Select @GET capabilites only LD (IX),A LD HL,FILIN ;Get the entry point LD (IX+1),L ;Store the address LD (IX+2),H RET ;Done! ; ; Print no DCB's available message ; NODCB STROUT NONDCB ;Print NO NEW DCB's message JP EXIT1 ;Exit from KERMIT ; ; Get a new line to print on ; NEWLIN PUSH AF ;Save the acumulator LD A,CR ;Get a equivilent CALL CONOUT ;Output it to the screen POP AF ;Restore A RET ;Return to caller ; ; Set the default disk drive command ; SETDSK EQU $ LD A,CMNUM ;PARSE A NUMBER CALL COMND JP KERMT3 OR A ;If no number than say bad command JP Z,KERMT2 LD A,D ;Check for number above 255 IFNZ SETDRV_2 ;Jump if number bigger than 255 LD C,E ;Get the lower order byte CALL XCHKDRV ;Check the disk drive JR NZ,SETDRV_2 ;Jump if TRSDOS doesn't like it PUSH BC ;Save the binary number JR NC,SETDRV_1 ;If carry set the drive is write protected STROUT WRTPROT ;Say drive is write protected SETDRV_1 STROUT DSKOK ;Say default drive changed POP BC ;Get the drive number back LD A,C ;Get the binary value into a ADD A,48 ;Make it and ASCII digit LD (DEFDSK),A ;Save it as the new default JP KERMIT ;Get a new command ; ; Print bad drive message ; SETDRV_2 LD A,32 ;Get the illegal drive message number CALL XERROR ;Have TRSDOS print the message JP KERMIT ;Go get a new command ; ; Clear any buffered characters from input buffer ; CLRPRT PUSH AF LD A,(NXTCHR) ;Set the next, and current positions LD (CURCHR),A ;within the buffer to be the same XOR A ;Set buffered character count to zero LD (INCNT),A LD (XOFREC),A ;Reset XOFF'd state LD (XFFLG),A ;Haven't sent XOFF either POP AF RET ; ; Display the directory ; ;This code makes an educated guess as to whether it is running on a ;6.1 or a 6.2 TRSDOS machine. This is to determine if we should ;issue the DIR command for 6.1 or the CAT command for 6.2 ; DIR EQU $ LD A,CMTXT ;Get text for DIR/CAT command LD DE,DIRBUF CALL COMND JP KERMT3 IFNZ DIR1C ;Jump if some text given DIR1B LD A,(DEFDSK) ;Otherwise, use default drive LD (DIRBUF),A ;Put in the text LD A,CR ;Put in the terminator LD (DIRBUF+1),A DIR1C CALL NEWLIN ;Get new lines CALL NEWLIN LD IY,(FLAGS) ;Check if using 6.1, or 6.2 TRSDOS LD A,(IY+27) ;Get the version number AND 0FH ;KEEP JUST THE X OF 6.X LD HL,DO62DR ;Get 6.2 command (CAT) IFA 2,DIR1E ;Jump if 6.2 LD HL,DO61DR ;Get 6.1 command (DIR) DIR1E LD DE,DIRCMD ;Where to put the text LD BC,4 ;How much to move PUSH DE ;Save the start LDIR ;Move the command POP HL ;Restore the start CALL XCMNDR ;Let TRSDOS do it for us DIR1D JP KERMIT ;Get a new command ; ; Erase a file from the system ; ERA EQU $ LD A,CMTXT ;Get some text LD DE,MFNBUF PUSH DE ;Save the buffer address CALL COMND JP KERMT3 IFZ ERA3 ;Jump if no text given CALL NEWLIN ;Get a newline POP HL ;Get the address back LD (MFNPTR),HL XOR A LD (LOGNAMES),A ;Reset the log names flag CALL BUILDF ;Do wild carding LD A,(FILECNT) ;Check if anything found IFZ ERA3 LD (MFNPTR),HL ;Save the start of the list ERA2 CALL MFNAME ;Get one filename from the buffer JR C,ERA3 ;Jump if no more LD DE,MFREQ ;Get the name LD B,0 ;Select 256 LRL LD HL,DATA ;Get the address of a temp buffer CALL XOPEN ;Try to open it JR Z,ERA1 ;Jump if opened CP 42 ;Was it an LRL error message? JR Z,ERA1 ;Jump if it was ERA0 CALL XERROR0 ;Issue the message indicated in A JR ERA3 ;Get a new command ; ; Print the removing message, then remove it ; ERA1 LD HL,FCB ;Convert ETX to EOS in FCB LD BC,32 ;Max distance LD A,3 ;What to find CPIR ;Look DEC HL ;Ignore errors LD (HL),EOS ;Change it STROUT REMOVSTR ;Output 'Removing: ' message STROUT FCB ;Output the filename CALL NEWLIN ;Get a newline LD DE,MFREQ ;Get the FCB CALL XKILL ;Remove the file JR Z,ERA2 ;Abort if error occurs JR ERA0 ;Get the next one ; ERA3 JP KERMIT ;Get a new command ; ; This routine sets up KERMIT/INI as initialization. The trick ; is to just make it look like the user typed 'TAKE KERMIT/INI'. ; CHKTAK CALL XFLAGS ;Get the flags area into IY LD A,(IY+10) ;Get the KFLAG$ AND 0F8H ;Reset the , and LD (IY+10),A ;the bits, and store it LD B,46 ;Pause for a good deal of time CALL XPAUSE LD A,(IY+10) ;Get the KFLAG$ mask back AND 7 ;Any of the keys pressed? RET NZ ;Stop if BREAK, ENTER, or PAUSE LD DE,TFCB ;LOAD THE FCB ADDRESS LD HL,TKNAME ;NAME OF THE FILE LD BC,TKLEN ;LENGTH OF THE STRING LDIR LD DE,TFCB ;GET IT AGAIN LD HL,TBUF ;GET THE INPUT BUFFER LD B,0 ;256 BYTE LRL CALL XOPEN ;OPEN THE FILE JR Z,CHKT_1 ;Jump if everything OK CP 42 RET NZ ;Return if NOT LRL error CHKT_1 LD A,1 ;SET THE TAKE COMMAND ACTIVE FLAG LD (TAKFLG),A RET ;GO DO IT. ; ; Print ESCAPE character sequence as CONTROL-? ; ESCPR LD A,(ESCCHR) ;GET THE ESCAPE CHAR. ESCPR1 IFAGE ' ',ESCPR2 ;IS IT A CONTROL CHAR? PUSH AF STROUT INMS10 ;Output CONTROL- POP AF ;GET THE CHAR BACK OR 100O ;DE-CONTROLIFY. ESCPR2 CALL CONOUT RET ; ; Swap screens between connect mode, and KERMIT command modes ; SWAPIN LD A,15 ;cursor off CALL CONOUT ;Tell *DO to turn it off LD HL,2600H ;Get the destination LD B,6 CALL XVDCTL ;Move screen image to temp space LD HL,SWTBUF ;Move the buffer to the screen LD B,5 CALL XVDCTL ;Move it LD HL,2600H ;Now move temp buffer to swap buffer LD DE,SWTBUF LD BC,1920 LDIR ;Move it LD A,14 ;cursor back on CALL CONOUT RET ;Return to the caller ; ; Put connect command screen in view ; SCRCON EQU $ CALL SWAPIN ;Swap screens LD B,4 ;Select get cursor position option CALL XVDCTL ;SVC @VDCTL to get position LD (CMDCRS),HL ;Save the cursor LD HL,(CONCRS) ;Get the connect cursor postion LD B,3 ;Select SET cursor position CALL XVDCTL ;SVC @VDCTL to set it LD A,14 ;Make sure that the cursor is ON CALL CONOUT RET ;Return to caller ; ; Swap in Kermit command screen ; SCRCMD EQU $ CALL SWAPIN ;Swap screens LD B,4 ;Get the current cursor position CALL XVDCTL ;SVC @VDCTL to get it LD (CONCRS),HL ;Save it LD HL,(CMDCRS) ;Get the Kermit command cursor position LD B,3 ;Set the current cursor position CALL XVDCTL ;SVC @VDCTL to set it LD A,14 ;Make sure the cursor is on CALL CONOUT RET ;Return ; ; *FI Device driver is here ; ; Valid memory module headers are used here, but are not necessary ; since the drivers are not in the High or Low memory chain of ; modules. ; FILIN JR INPFIL ;Jump to code DW ENDIN ;End of module DB 4 ;Module name length DB 'INP$' FINDCB DW 0 ;Pointer to our DCB DW 0 PRECHR DB 0 ;Previous character received INPFIL CALL INPORT ;Get an input character JR Z,INP04 ;Jump if successful CALL CONIN ;Failed, read the keyboard IFZ INPFIL ;Jump if no key pressed IFANOT 128,INP03 ;Jump if not break LD A,28 ;Return at EOF indicator OR A ;Set NZ status RET ;return to caller INP03 LD E,A ;Get the keyboard character CALL OUTCHR ;Output it to the port JR INPFIL ;Read the port again INP04 LD C,A ;Get the input character LD A,(FLOFLG) ;Are we doing flow control? IFNZ INP05 ;Jump if not doing flow control LD A,C ;Get the character back IFA XON,INPFIL ;Ignore XON if sent IFA XOFF,INPFIL ;Ignore that also INP05 LD A,(PRECHR) ;Get the previous character CP CR ;Was it CR? LD A,C ;Get the current character JR NZ,INP09 ;Jump if not CR LD A,(FILTYPE) ;Check if should convert OR A ;Is it binary mode? LD A,C JR NZ,INP09 ;It is, so do not translate CP LF ;Is the current character LF? LD (PRECHR),A ;Store new previous JR Z,INPFIL ;Ignore LF after CR INP09 CP A ;Set Z status RET ;Return byte to caller in A ENDIN EQU $ ; ; *FO Device driver is here ; FILOUT JR FIOUT ;Jump to code DW OUTEND-1 ;Normal header DB 4 DB 'OUT$' FOTDCB DW 0 DW 0 FIOUT LD E,C ;Get the character to send FIOUT1 CALL OUTCHR ;Output it. We will hang till output LD A,C ;Get the character sent CP A ;Set the Z flag RET ;Return the byte sent out, and Z status OUTEND EQU $ ; end of file <<< m4chgs.asm >>> ; m4chgs/asm Version 5.2 9/21/86 Change ? to not destroy the screen while in connect mode. Save screen, and then restore it after the user presses a key. 9/20/86 Fix bug in SET KEY that caused garbage to be returned when a new key was defined after ANY key definition was used. 7/20/86 Moved SET FILE-WARNING to SET FILE WARNING. 7/1/86 Add wild carding to KILL command. 6/15/86 Add transaction and DEBUG logging. 6/14/86 Fixed dumb terminal emulation, and moved DUMB terminal translations to TRMOUT() so that LOCAL ECHO would also work correctly. 6/6/86 Changed FILE-TYPE, and FILE-DISPOSITION to be options under a new SET value called FILE. Now the corresponding commands are SET FILE TYPE, and SET FILE DISPOSITION. 6/6/86 SHOW was changed also to reflect the changes in SET. 6/3/86 Add (SYSTEM,INVIS) parameters to send command to allow these types of files to be ignored. Neither type is allowed by default. The first letter is enough to qualify the full name. 5/30/86 Fixed problem with ^C and ^E exits from the protocol. Changed CALL XKLTSK to JP XKLTSK. TRSDOS evidently did not like the extra word on the stack. 5/30/86 Fix error is LOGOUT, BYE, and FINISH retry handling that caused weird behavior when MAXTRY retries were reached. 5/29/86 Logging now translates CR/LF pairs to just CR 5/28/86 Added wild carding to SEND command Version 5.1 (Never released) 5/24/86 Restructure output of SHOW ALL to include everything 5/2/86 Make it possible to use break to abort a PAUSE 5/2/86 Fixed problem with PAUSE, backwards test changed. This error made PAUSE work for one second, no matter what the parameter was. Version 5.0 A large number of changes were made between version 5 and version 4. Added REMOTE commands, restructured the code quite a bit to clean up some things. There were too many changes to document all of them here. ; end of file  <<< m4cmd.asm >>> ; M4CMD/ASM ; ; Jumping to this location will cause the return address on the ; stack to be incremented by 3, and then jumped to. This is used ; in several places to make error handling easier. Code using ; this mechanism might look like. ; ; ROUTINE: EQU $ ; ... ; CALL SPACK ; JP ABORT ;Die on an error ; ... ;Continue normally ; ; RET ; SPACK: EQU $ ; ... ; LD A,B ;Check result ; CP C ;Must be equal ; RET NZ ;Error if not equal ; LD A,(LEN) ;Get the length for return ; JP RSKP ;Normal return ; RSKP POP HL ;GET THE RETURN ADDRESS. INC HL ;INCREMENT BY THREE. INC HL INC HL JP (HL) ;Return to return+3 bytes ; ; Output the value in HL as an ASCII decimal string ; NOUT EQU $ PUSH HL ;Save the registers PUSH BC PUSH DE LD DE,NBUFF ;Get the string buffer PUSH DE ;Save the address CALL XHEXDEC ;Convert from binary to ASCII EX DE,HL ;HL = end of buffer + 1 LD (HL),EOS ;Add EOS for printing POP HL ;Restore the starting address LD A,' ' ;Remove leading spaces NOUT1 IFANOT (HL),NOUT2 ;Go if not blank INC HL ;Point to next character JR NOUT1 ;Back to top of loop NOUT2 EX DE,HL ;DE is now start of string to print CALL PRTSTR ;Print the number POP DE ;Restore the registers POP BC POP HL RET ; ; ; Command parsing routines ; ; This routine prints the prompt pointed to by DE, and then ; sets up the appropriate values to allow a reparse at any point ; PROMPT POP HL ;Get the return address PUSH HL ;Put it back LD (CMRPRS),HL ;Save it as the reparse address LD (CMOSTP),SP ;Save the stack pointer as well LD (CMPRMP),DE ;Save the prompt to print LD HL,CMDBUF ;Get the start of the command buffer LD (CMCPTR),HL ;Initialize the pointer into it LD (CMDPTR),HL ;Save 2 copies XOR A LD (CMAFLG),A ;Zero the flags LD (CMCCNT),A ;No characters CPL ;Make it non zero LD (CMSFLG),A ;Set these flags LD A,(TAKFLG) ;Check if take is active IFZ PRMT10 ;Jump if not LD A,(TAKLOG) ;Is the take-file display flag set? IFZ PRMT20 ;Jump if not PRMT10 CALL NEWLIN ;Get a newline LD DE,(CMPRMP) ;Print the prompt CALL PRTSTR PRMT20 RET ;Return to the caller ; ; Come to here to initiate a reparse ; REPARS LD SP,(CMOSTP) ;GET THE OLD STACK POINTER. LD HL,CMDBUF LD (CMDPTR),HL LD A,0FFH ;TRY IT THIS WAY (DAPHNE.) LD (CMSFLG),A LD HL,(CMRPRS) ;GET THE REPARSE ADDRESS. JP (HL) ;GO THERE. ; ;THIS ADDRESS CAN BE JUMPED TO ON A PARSING ERROR. ; PRSERR LD SP,(CMOSTP) ;GET THE OLD STACK POINTER. LD HL,CMDBUF LD (CMCPTR),HL ;INITIALIZE THE COMMAND POINTER. LD (CMDPTR),HL CALL NEWLIN XOR A LD (CMAFLG),A ;ZERO THE FLAGS. LD (CMCCNT),A LD A,0FFH ;TRY IT THIS WAY (DAPHNE.) LD (CMSFLG),A LD DE,(CMPRMP) ;GET THE PROMPT. CALL PRTSTR LD HL,(CMRPRS) JP (HL) ; ;This routine parses the specified function in A. Any additional ;information is in DE and HL. ; Returns to RETURN+3 on success ; Returns to RETURN on failure. (Assumes that a JP follows CALL) ; COMND LD (CMSTAT),A ;Save what we are presently parsing. CALL CMINBF ;Get chars until action or erase char. CP CMNUM ;Is the function "PARSE a number"? JP Z,CMDNUM ;Jump if so CP CMCFM ;Parse a confirm? JP Z,CMCFRM ;Jump if so CP CMKEY ;Parse a keyword from a table? JP Z,CMKEYW ;Jump if so CP CMIFI ;Parse a file spec? JP Z,CMIFIL ;If so jump CP CMIFIN ;Other file type? JP Z,CMIFIL ;If so use same routine CP CMOFI ;ditto JP Z,CMIFIL CP CMTXT ;Parse a text string? JP Z,CMTEXT ;If so jump LD DE,CMER00 ;Otherwise parser calling error CALL PRTSTR ;So print a message RET ;And return error ; ;This routine parses arbitrary text up to a ; ; DE=address of text buffer ; ; A=number of characters typed (zero or more) on return ; CMTEXT EX DE,HL ;Put the pointer to the buffer in HL LD (CMPTAB),HL ;Save the pointer LD B,0 ;Initialize the count to zero CMTXT1 CALL CMGTCH ;Get a character OR A ;Test the high bit for some terminator JP P,CMTXT5 ;If not then jump AND 7FH ;Turn off the high bit CP ESC ;Is it escape RET Z ;Return failure if so CMTXT2 IFA '?',CMTXT7 ;Jump if the user needs help IFA ' ',CMTXT5 ;If blank, add it to text LD A,B ;Get the counter LD HL,(CMPTAB) ;Get the updated pointer LD (HL),CR ;Put the terminator in EX DE,HL ;Move ending pointer to DE JP RSKP ;Return success ; CMTXT3 LD HL,CMAFLG ;Point to the action flag LD (HL),0 ;Reset it CMTXT5 INC B ;Add one to the count of characters CMTXT6 LD HL,(CMPTAB) ;Get the pointer PUTHL A ;Add the character and increment LD (CMPTAB),HL ;Save the update pointer JR CMTXT1 ;Go get another character ; CMTXT7 LD DE,TXTHLP ;Get the help message CALL REPRNT ;Print the message JP REPARS ;Jump to the reparse ; ;This routine parses an input number in ASCII decimal ; CMDNUM LD B,0 ;Reset the character count LD HL,0 ;Initialize the value to zero LD (THEVAL),HL CMNM10 CALL CMGTCH ;Get a character OR A ;Check for high bit set terminator JP P,CMNM50 ;Jump if not AND 7FH ;Trim the high bit CP ESC ;Is it ESCAPE (abort) RET Z ;Return error if so CMNM20 IFA '?',CMNM70 ;Go if the user needs help LD A,B ;Get the count LD DE,(THEVAL) ;Get the number found JP RSKP ;Return success ; CMNM50 INC B ;Add one to count of characters PUSH HL ;Save the values PUSH DE PUSH BC LD HL,(THEVAL) ;Get the current number LD C,10 ;Multiply by 10 PUSH AF ;Save AF too CALL XMUL16 ;Multiply 8 bit by 16 bit LD H,L ;Move the 24 bit result into HL as 16 LD L,A POP AF ;Get the character to add SUB 48 ;Convert to a binary number JP P,CMNM60 ;Jump if no underflow CMNM55 POP BC ;Restore the regs POP DE POP HL LD DE,ERMES2 ;Print error message CALL PRTSTR JP KERMIT ;GET A NEW COMMAND ; CMNM60 IFAGE 10,CMNM55 ;Jump if too big LD C,A ;Get it into BC for 16 bit MATH LD B,0 ;Zero the MSB ADD HL,BC ;Compute the new number LD (THEVAL),HL ;Save the result POP BC ;Restore the registers POP DE POP HL JR CMNM10 ;Loop on ; CMNM70 LD DE,NUMHLP ;Get the HELP message CALL REPRNT ;Print the message, and reprint prompt JP REPARS ;Plus the rest of the text, and restart ; ; Get a confirmation of the command by accepting only ; CMCFRM CALL CMGTCH ;GET A CHARACTER FROM THE BUFFER OR A ;WHAT WAS IT, CONTROL? RET P ;NOPE, SO EXIT VIA ERROR RETURN AND 7FH ;STRIP THE SIGN BIT FLAG IFANOT '?',CMCFR3 ;Go if not help request LD DE,CMIN00 ;TELL THEM NO MORE HELP CALL REPRNT ;PRINT THE MESSAGE JP REPARS ;PRINT THE MESSAGE AND THE PROMPT AGAIN CMCFR3 CP ESC ;IS IT ABORT? RET Z ;TAKE ERROR EXIT IF SO JP RSKP ;TAKE NORMAL RETURN ;THIS ROUTINE PRINTS THE MESSAGE IN DE AND SETS UP FOR A REPARSE REPRNT CALL PRTSTR XOR A LD (CMAFLG),A CALL NEWLIN LD DE,(CMPRMP) CALL PRTSTR LD HL,(CMCPTR) DEC HL LD (HL),EOS LD (CMCPTR),HL LD DE,CMDBUF CALL PRTSTR RET ;THIS ROUTINE PARSES A KEYWORD FROM THE TABLE POINTED ;TO IN DE. THE FORMAT OF THE TABLE IS AS FOLLOWS ; ;ADDR DB N Where N is the number of entries in the table ; DB K Where K is 2+length of longest keyword. ; Repeated for each entry in the table... ; DB M Where M is the length of the keyword ; DB 'STRING',EOS Where string is the KEYWORD. ; DB A,B Where A & B are pieces of DATA ; to be returned, (Must be two bytes worth) ; ;THE KEYWORDS MUST BE IN ALPHABETICAL ORDER. ;**** NOTE THE DATA VALUE A IS RETURNED IN REGISTERS A AND E. THE ;**** DATA VALUE B IS RETURNED IN REGISTER D. THIS ALLOWS THE TWO DATA ;BYTES TO BE STORED AS ;DW XXX ;AND RESULT IN A CORRECTLY FORMATTED 16-BIT VALUE IN REGISTER PAIR ;DE. CMKEYW LD (CMPTAB),DE ;SAVE THE BEGINNING OF KEYWORD for ? LD A,(DE) ;GET THE NUMBER OF ENTRIES IN THE TABLE. LD B,A ;SAVE IN B INC DE ;Point past the keyword count INC DE ;POINT PAST THE MAX LENGTH NUMBER LD (CMKPTR),DE ;Save it for later LD HL,(CMDPTR) ;Save the command buffer pointer LD (CMSPTR),HL CMKEY2 LD A,B ;Get the keyword counter OR A ;ANY LEFT? RET Z ;IF NOT WE FAILED. LD HL,(CMKPTR) ;Get the current keyword pointer INC HL ;Skip the visibility LD E,(HL) ;Get the length of the keyword INC HL ;Skip the length CMKEY3 DEC E ;DECREMENT THE NUMBER OF CHARS LEFT. LD A,E CP -1 JP M,CMKEY5 ;IF SO GO TO THE NEXT. CALL CMGTCH ;GET A CHAR. OR A ;IS IT A TERMINATER? JP P,CMKEY4 ;IF POSITIVE, IT IS NOT. AND 7FH ;TURN OFF THE MINUS BIT. CP '?' ;Is this help? JP NZ,CMKY35 PUSH HL ;SAVE HL FOR A SEC PUSH DE XOR A LD (CMAFLG),A ;TURN OFF THE ACTION FLAG. LD DE,HLPMES ;PRINT ONE OF THE FOLLOWING... CALL PRTSTR LD HL,CMCCNT ;DECREMENT THE CHAR COUNT. DEC (HL) POP DE POP HL LD HL,(CMPTAB) ;GET THE START OF THE KEYWORD TABLE LD B,(HL) ;B IS HOW MANY IN THE TABLE INC HL ;Point at the column spacing value LD A,(HL) ;Get the length LD (MAXLEN),A ;Save it for later XOR A LD (CURCOL),A ;Set column to starting column INC HL ;Point at the visible attribute CM1010 LD A,(HL) ;Get the visibility LD (VISIBLE),A INC HL ;POINT AT THE FIRST ENTRY LD C,(HL) ;C IS HOW MANY CHARACTERS IN NAME LD A,C ;SAVE THE LENGTH FOR LATER LD (CURLEN),A INC HL ;POINT AT THE TEXT FOLLOWING LD (CMKPTR),HL ;SAVE THE ADDRESS TO PRINT FROM ON MATCH LD DE,(CMSPTR) ;GET THE ADDRESS OF THE TYPED KEYWORD CM1020 LD A,(DE) ;GET A CHARACTER IFA '?',CM1040 ;Go if request for help CALL CAPTAL ;MAKE SURE LETTERS ARE UPPER CASE INC DE ;POINT TO THE NEXT. CP (HL) ;SAME AS IN KEYWORD TABLE? INC HL ;POINT TO THE NEXT JR NZ,CM1050 ;JUMP IF NO MATCH DEC C ;ONE LESS CHARACTER IN THE KEYWORD JP P,CM1020 LD A,(DE) IFA '?',CM1040 ;Jump if help request CP 0 ;Set flags to P,NZ JP CM1050 ;Join other code CM1040 EQU $ LD A,(VISIBLE) ;Is this a visible command? IFZ CM1045 ;Jump if it is not PUSH DE ;SAVE THE REGS PUSH HL PUSH BC LD DE,(CMKPTR) ;Get the string CALL STRLEN ;Get length into BC LD A,(MAXLEN) ;Get the padded length LD B,A ;Save it for now LD A,(CURCOL) ;Get current screen column ADD A,B ;Compute new column LD B,A ;Save it LD A,(MAXCOL) ;Get right margin IFALT B,CM1042 ;Are we passed the edge? Jump if so LD A,B ;Get new column LD (CURCOL),A ;Save it LD A,(MAXLEN) JR CM1043 ;Join code CM1042 CALL NEWLIN ;Print a newline LD A,(MAXLEN) ;Get the padded length LD (CURCOL),A ;Set new position CM1043 SUB C ;Compute blanks to print LD C,A ;Put it into C PUSH BC ;Save count for now LD DE,(CMKPTR) ;Get the string to print CALL PRTSTR ;Print the keyword POP BC ;Restore count CM1044 LD A,' ' ;Get a blank CALL CONOUT ;Display it DEC C ;Decrement counter JR NZ,CM1044 ;Jump if not there POP BC ;RESTORE THE REGS POP HL POP DE CM1045 LD A,3 ;SKIP OVER THE EOS AND THE DISCRIPTOR ADD A,C ;PLUS THE CHARACTERS LEFT IN THE STRING LD E,A ;PUT IT IN DE TO ADD LD D,0 ;MAKE IT A BYTE VALUE IN 16 BITS ADD HL,DE ;GOT THE NEW ADDRESS DJNZ CM1010 ;GET THE NEXT JR CM1190 ;END OF THE TABLE CM1050 DEC HL ;CORRECT HL FROM LAST INCREMENT JP P,CM1045 ;IF (TABLE) > (COMMAND) KEEP LOOKING JR Z,CM1045 XOR A ;RESET THE ACTION FLAG LD (CMAFLG),A CM1190 CALL NEWLIN ;PRINT A NEW LINE CM1200 CALL NEWLIN ;PRINT A NEW LINE LD DE,(CMPRMP) ;GET THE PROMPT TO REPRINT CALL PRTSTR ;PRINT IT LD HL,(CMDPTR) ;GET THE END OF THE COMMAND LINE LD (HL),EOS ;TERMINATOR FOR PRINTING LD HL,(CMCPTR) ;GET THE LAST CHARACTER DEC HL LD (CMCPTR),HL ;IGNORE THE '?' AT THE END LD DE,CMDBUF ;GET THE START OF THE BUFFER CALL PRTSTR ;PRINT THE COMMAND LINE JP REPARS ;REPARSE THE ENTIRE LINE CMKY35 CP ESC RET Z PUSH HL PUSH DE CALL CMAMBG JP CMKY36 LD HL,(CMCPTR) ;GET THE END OF THE COMMAND LD BC,CMDBUF ;GET THE START OF THE BUFFER OR A ;RESET THE CARRY SBC HL,BC ;COMPUTE THE OFFSET LD DE,CMER01 CALL PRTSTR ;SAY ITS AMBIGUOUS. JP PRSERR ;GIVE UP. CMKY36 POP DE POP HL CMKY37 INC E ;ADD ONE IN CASE IT IS NEGATIVE. LD D,0 ADD HL,DE ;INCREMENT PAST THE KEYWORD. INC HL ;PAST THE EOS. LD E,(HL) ;GET THE DATA. INC HL LD D,(HL) LD A,E JP RSKP CMKEY4 CALL CAPTAL ;MAKE IT UPPER CASE IF LOWER CMKY41 CP (HL) ;Check the next character JR NZ,CMKEY5 INC HL JP CMKEY3 CMKEY5 LD D,0 LD A,E ;GET THE NUMBER OF CHARS LEFT. OR A ;IS IT NEGATIVE? JP P,CMKY51 LD D,0FFH CMKY51 EQU $ ADD HL,DE ;INCREMENT PAST THE KEYWORD. INC HL ;PLUS 4 INC HL INC HL INC HL LD (CMKPTR),HL DEC B ;DECREMENT THE NUMBER OF ENTRIES LEFT. LD HL,(CMSPTR) ;GET THE OLD CMDPTR. LD (CMDPTR),HL ;RESTORE IT. JP CMKEY2 ;GO CHECK THE NEXT KEYWORD. ;CONVERT CONTENTS OF A TO UPPER CASE IF IT IS LOWER CAPTAL IFALT 'a',CAPS10 IFAGE 'z'+1,CAPS10 AND 137O ;MAKE IT UPPER CASE CAPS10 RET ;RETURN TO THE CALLER ;CHECK AMBIGUITY OF A COMMAND CMAMBG DEC B ;DECREMENT THE NUMBER OF ENTRIES LEFT. RET M ;IF NONE LEFT THEN IT IS NOT AMBIGUOUS. INC E ;THIS IS OFF BY ONE;ADJUST. LD C,E ;SAVE THE CHAR COUNT. LD A,E OR A ;ANY CHARS LEFT? RET Z ;NO, IT CAN'T BE AMBIGUOUS. LD D,0 ADD HL,DE ;INCREMENT PAST THE KEYWORD. LD E,4 ;PLUS THE EOS AND DATA. ADD HL,DE LD B,(HL) ;GET THE LENGTH OF THE KEYWORD. INC HL EX DE,HL LD HL,(CMKPTR) ;GET POINTER TO KEYWORD ENTRY. INC HL LD A,(HL) ;GET THE LENGTH OF THE KEYWORD. SUB C ;SUBTRACT HOW MANY LEFT. LD C,A ;SAVE THE COUNT. IFA B,CMAMB0 RET P ;IF LARGER THAN THE NEW WORD THEN NOT AMB CMAMB0 LD HL,(CMSPTR) ;GET THE POINTER TO WHAT PARSED. CMAMB1 DEC C ;DECREMENT THE COUNT. JP M,RSKP ;IF WE ARE DONE THEN IT IS AMBIGUOUS. EX DE,HL ;EXCHANGE THE POINTERS. LD B,(HL) ;GET THE NEXT CHAR OF THE KEYWORD INC HL EX DE,HL ;EXCHANGE THE POINTERS. LD A,(HL) ;GET THE NEXT PARSED CHAR. INC HL CALL CAPTAL ;MAKE IT UPPER IF LOWER CMAMB2 CP B ;ARE THEY EQUAL? RET NZ ;IF NOT THEN ITS NOT AMBIGUOUS. JP CMAMB1 ;CHECK THE NEXT CHAR. ; ; Parse a file specification. This includes a call to @FSPEC to ; do case conversion, and any other necessary stuff to make a ; legal file spec. On normal return, A has the count of characters ; that are in the passed buffer ; CMIFIL LD (CMFCB),DE ;SAVE WHERE TO PUT THE CHARACTERS LD DE,CLBUF LD B,0 ;Set the count to zero CMIFI1 CALL CMGTCH ;GET A CHARACTER OR A ;CHECK FOR A CONTROL CHARACTER ?,CR,ESC JP P,CMIFI3 ;GO IF NOT CONTROL AND 7FH ;STRIP THE HIGH BIT CP ESC ;WAS IT ABORT? RET Z ;TAKE THE ERROR EXIT IFANOT '?',CMIFI4 ;Go if not help request LD DE,FILHLP ;PRINT A MESSAGE CALL REPRNT ;SET UP FOR REPARSE JP REPARS ;GET A NEW CHARACTER CMIFI3 LD (DE),A ;STORE THE CHARACTER INC DE ;POINT TO NEXT POS INC B ;INCREMENT CHARACTER COUNT JR CMIFI1 ;GET ANOTHER ONE CMIFI4 LD A,CR ;Get the end of name marker LD (DE),A ;Put in a terminator LD A,B ;Get the count IFZ CMIFI5 ;Skip fspec if no characters given PUSH HL ;Save the pointer LD HL,CLBUF ;GET THE TEXT TO FSPEC LD DE,(CMFCB) ;WHERE TO PUT THE RESULT CALL XFSPEC ;MAKE IT A FILE SPEC JP NZ,CMIFI6 ;Oops, bad fspec EX DE,HL ;Move start to HL LD A,3 ;Get the character to find LD BC,40 ;Get the maximum distance to look CPIR ;Find it LD HL,39 ;Find out how far we looked OR A ;Reset the carry SBC HL,BC ;Compute the distance LD B,L ;Get the length POP HL ;Restore pointer which is... CMIFI5 LD (CMDPTR),HL ;Next place to put characters at LD A,B ;Copy the length to A JP RSKP ;Return normal ; CMIFI6 POP HL ;Restore the stack JP XERROR0 ;Print a system message and return ; ; Get input characters from the keyboard, up to an action character ; The actual character input is retrieved via GETSTR(). ; CMINBF PUSH AF PUSH DE PUSH HL LD A,(CMAFLG) ;IS THE ACTION CHAR FLAG SET? IFNZ CMINB9 ;Go if it is LD HL,(CMCPTR) ;Get the position PUSH HL ;Save it for later LD DE,CMDBUF ;Get EOB OR A ;Reset carry SBC HL,DE ;Compute number of characters typed in LD B,L ;Get number of characters POP HL ;Get the value back CALL GETSTR ;Input up to an action character JP C,PRSERR ;Jump if user pressed break LD A,B ;SAVE THE COUNT LD (CMCCNT),A LD C,B ;GET THE NUMBER OF CHARACTERS IN BUFFER LD B,0 LD HL,CMDBUF ;Get the start PUSH HL ;Save it ADD HL,BC ;Add the count LD (CMCPTR),HL ;Save next input position POP BC ;Get the start OR A ;Reset the carry SBC HL,BC ;Are there any characters in the buffer? JP Z,PRSERR ;IF NO CHARACTERS START OVER CMINB6 LD A,0FFH ;SET THE ACTION FLAG. LD (CMAFLG),A CMINB9 POP HL ;Restore the registers POP DE POP AF RET ;Return ; ; Get a character from the command input buffer. If an action ; character is found, then the MSB of the character will be set ; CMGTCH PUSH HL PUSH BC CMGTC1 LD A,(CMAFLG) OR A ;IS IT SET. CALL Z,CMINBF ;IS THE ACTION CHAR FLAG SET? LD HL,(CMDPTR) ;GET A POINTER INTO THE BUFFER. LD A,(HL) ;GET THE NEXT CHAR. INC HL LD (CMDPTR),HL IFA ' ',CMGTC2 IFANOT TAB,CMGTC3 CMGTC2 LD A,(CMSFLG) ;GET THE SPACE FLAG. IFNZ CMGTC1 ;Was last char a space? LD A,0FFH ;SET THE SPACE FLAG. LD (CMSFLG),A LD A,' ' POP BC POP HL JR CMGTC5 CMGTC3 PUSH AF XOR A LD (CMSFLG),A ;ZERO THE SPACE FLAG. POP AF POP BC POP HL IFA ESC,CMGTC5 ;Go if escape abort IFA '?',CMGTC4 ;Go answer a help request IFA CR,CMGTC4 CP LF RET NZ ;NOT AN ACTION CHAR, JUST RETURN. CMGTC4 PUSH HL LD HL,(CMDPTR) DEC HL LD (CMDPTR),HL POP HL CMGTC5 OR 80H ;MAKE THE CHAR NEGATIVE TO INDICATE IT IS RET ;A TERMINATOR. STRLEN EQU $ PUSH AF PUSH DE LD BC,0 STRLEN_1 EQU $ LD A,(DE) IFA EOS,STRLEN_2 INC DE INC BC JR STRLEN_1 STRLEN_2 EQU $ POP DE POP AF RET ;end of file <<< m4equ.asm >>> ; ; Symbolic defintions for some ASCII characters ; EOS EQU 0 ;Printed string terminator BELL EQU 07O ;ASCII BEL (CONTROL-G) CTRLC EQU 03O ;ASCII ETX (CONTROL-C) TAB EQU 11O ;ASCII TAB (CONTROL-I) LF EQU 12O ;ASCII LINE FEED (CTRL-J) FF EQU 14O ;ASCII FORM FEED (CTRL-L) CR EQU 15O ;ASCII CARRIAGE RETURN (CTRL-M) XON EQU 21O ;THE THE ASCII CHARACTER USED FOR XON XOFF EQU 23O ;THE THE ASCII CHARACTER USED FOR XOFF ESC EQU 33O ;ASCII ESCAPE SUBT EQU 32O ;ASCII SUB (CTRL-Z) DEL EQU 177O ;ASCII DELETE (RUBOUT) DEFESC EQU 31 ; KEY ON KEY BOARD MAXPKT EQU '~'-' '+2O ;MAXIMUM SIZE OF A PACKET. DRPSIZ EQU 5EH ;DEFAULT RECEIVE PACKET SIZE. DSPSIZ EQU 20H ;DEFAULT SEND PACKET SIZE. DSTIME EQU 15 ;DEFAULT SEND TIME OUT INTERVAL. DRTIME EQU 10 ;DEFAULT RECEIVE TIME OUT INTERVAL. DSPAD EQU 00H ;DEFAULT SEND PADDING. DRPAD EQU 00H ;DEFAULT RECEIVE PADDING. DSPADC EQU 00H ;DEFAULT SEND PADDING CHAR. DRPADC EQU 00H ;DEFAULT RECEIVE PADDING CHAR. DSEOL EQU CR ;DEFAULT SEND EOL CHAR. DREOL EQU CR ;DEFAULT RECEIVE EOL CHAR. DSQUOT EQU '#' ;DEFAULT SEND QUOTE CHAR. DRQUOT EQU '#' ;DEFAULT RECEIVE QUOTE CHAR. DSCHKT EQU '1' ;DEFAULT CHECKSUM TYPE SOH EQU 01H ;START OF HEADER CHAR. CMKEY EQU 01H ;PARSE A KEYWORD. CMIFI EQU 02H ;PARSE AN INPUT FILE SPEC. CMOFI EQU 03H ;PARSE AN OUTPUT FILE SPEC. CMCFM EQU 04H ;PARSE A CONFIRM. CMTXT EQU 05H ;PARSE TEXT. CMNUM EQU 06H ;PARSE ASCII DECIMAL STRING CMIFIN EQU 10H ;PARSE AN INPUT FILE SPEC <<< m4file.asm >>> ; m4file/asm ; ; The close command. At present, only SESSION is valid ; CLSFLS CALL GETLOGF ;Get the logfile descriptor IFNZ CLSF10 ;Skip if not SESSION LOG FILE LD A,(LOGFLG) ;Check to see if session log open IFZ CLSF07 ;If already closed, then jump to message XOR A ;Reset the FILE OPEN flag LD (LOGFLG),A LD DE,LFCB ;Get the FCB for the CLOSE CALL XCLOSE ;Close the file if possible CALL NZ,XERROR0 ;Print a message if file not closed right JR CLSF08 ;Back for another command CLSF07 STROUT NOLOGF ;Print LOG FILE NOT OPEN message CLSF08 JP KERMIT ;Back for another command ; ; Check the debug logfile ; CLSF10 IFANOT 1,CLSF30 ;If not debug then try transaction LD A,(DEBLOG) ;Check if logging in effect IFZ CLSF07 XOR A ;Zap the open flag LD (DEBLOG),A LD DE,DFCB ;Get the FCB CALL XCLOSE CALL NZ,XERROR0 JR CLSF08 ; ; Check the transaction logfile ; CLSF30 LD A,(TRANLOG) ;Check if it is open IFZ CLSF07 XOR A ;Zap the open flag LD (TRANLOG),A ;Reset it LD DE,TRFCB ;Get the transaction FCB CALL XCLOSE ;Close the file CALL NZ,XERROR0 ;Print system message if error JR CLSF08 ;Back for another command ; ; THIS IS THE LOG COMMAND. ; LOG EQU $ CALL GETLOGF ;Get the logfile descriptor OR A JP Z,LOGSES ;If zero then session logging CP 2 JP Z,LOGTRAN ;Go do transaction logging ; ; Debug logging ; LD A,(DEBLOG) ;See if logging already in effect IFZ LOG_3 LOG_1 STROUT LOGOPN ;Print LOG OPEN message JP KERMIT ;RETURN TO COMMAND PARSER LOG_3 LD DE,DFCB PUSH DE ;Save it for later LD A,CMIFI ;Get a file spec CALL COMND ;Parse it JP KERMT3 ;Exit if not confirmed IFNZ LOG_3A LD HL,DEFDEBLOG ;Get the default name LD DE,DFCB LD BC,32 LDIR ;Move it into place LOG_3A POP DE ;Get the FCB back LD HL,DBUFF ;Get the buffer LD B,0 ;Use 256 LRL CALL XINIT ;Create the output file JR Z,LOG_5 IFA 42,LOG_5 ;Ignore a LRL error LOG_4 CALL XERROR0 JP KERMIT LOG_5 LD A,1 LD (DEBLOG),A ;Set the log file open flag JP KERMIT ; ; Session logging ; LOGSES LD A,(LOGFLG) ;Check if session log open IFZ LOG_6 JP LOG_1 ;Oops, log already open LOG_6 LD A,CMIFI ;PARSE AN INPUT FILE SPEC. LD DE,LFCB ;Get the session log FCB PUSH DE ;Save it for later CALL COMND ;Parse it JP KERMT3 IFNZ LOG_6A ;Jump if text was given LD HL,DEFSESLOG ;Get the default name LD DE,LFCB ;Get the FCB LD BC,32 ;Get the count LDIR ;Move the block LOG_6A LD HL,LBUFF ;Get the buffer POP DE ;Get the session log FCB LD B,0 ;Select 256 byte records CALL XINIT ;Create a new file JR Z,LOG_8 ;Continue on a no error return IFANOT 42,LOG_4 ;If not LRL error, then abort LOG_8 XOR A LD (PREVLCHR),A ;Reset the previous character LD A,2 LD (LOGFLG),A ;Turn logging on JP KERMIT ;Jump to get a new command ; ; Transaction logging ; LOGTRAN LD A,(TRANLOG) ;Get the flag IFZ LOG_9 JP LOG_1 ;Oops log already open LOG_9 LD A,CMIFI ;Get a file spec LD DE,TRFCB PUSH DE ;Save it for later CALL COMND ;Parse a file name JP KERMT3 ;Abort if no confirm IFNZ LOG_9A ;Jump if text given LD HL,DEFTRLOG ;Get the default LD DE,TRFCB LD BC,32 LDIR ;Move it LOG_9A POP DE LD HL,TBUFF ;Get the buffer LD B,0 ;Select 256 LRL CALL XINIT ;Create the output file JR Z,LOG_10 IFANOT 42,LOG_4 LOG_10 LD A,1 ;Set the flag to ON LD (TRANLOG),A JP KERMIT ;Back for another command ; ; Get a logfile identifier ; GETLOGF LD A,CMKEY ;PARSE A KEYWORD LD DE,CLSTAB ;GET THE PARSE TABLE CALL COMND ;GET A KEYWORD JP KERMT2 ;ABORT ON AN ERROR RET ;Return to caller ; ; Output a normal string terminated by EOS. ; OUTLOG LD A,EOS JP OUTLOGCH ; ; Output a message to a log file ; HL=message, DE=FCB, A=terminator character ; OUTLOGCH EQU $ PUSH HL ;Save the registers PUSH DE LD (ENDCH),A ;Store the terminator OUTL_1 LD A,(HL) ;Get a character CP EOS ENDCH EQU $-1 ;Address of terminator character JR Z,OUTL_2 PUSH HL ;Save the string address, and the FCB PUSH DE CALL XPUT ;@PUT the character POP DE ;Restore the addresses POP HL JR NZ,OUTL_3 ;On error, abort INC HL ;Point to next character JR OUTL_1 ;Loop on OUTL_2 POP DE ;Restore stack POP HL JP RSKP ;Return normal ; ; Log file error ; OUTL_3 CALL XERROR0 ;Print system message STROUT LOGERROR ;Print a message on the console POP DE ;Restore the stack POP HL RET ;Return error ;end of file <<< m4get.asm >>> ; M4GET/ASM ; RECEIVE COMMAND READ EQU $ CALL NEWLIN NSTATE 'R' ;Set initial protocol state LD DE,DATA ;WHERE TO PUT THE TEXT (IF ANY.) LD A,CMTXT CALL COMND ;GET EITHER SOME TEXT OR A CONFIRM. JP KERMT3 ;DIDN'T GET ANYTHING. OR A ;GET ANY CHARS? JR Z,READ1 ;NOPE, JUST A REGULAR SEND. LD (ARGBLK+1),A ;STORE THE NUMBER OF CHARS. LD (TEMP4),A ;Save the length EX DE,HL ;GET POINTER INTO HL. LD (HL),EOS ;Put in the print terminator NSTATE 'r' ;Set state to receive init with file READ1 CALL INIT ;Clear input line and init buffers LD HL,0 ;Reset all the flags LD (NUMPKT),HL ;SET THE NUMBER OF PACKETS TO ZERO. LD (NUMRTR),HL ;SET THE NUMBER OF RETRIES TO ZERO. LD (KTRANS),HL XOR A LD (PKTNUM),A ;SET THE PACKET NUMBER TO ZERO. LD (NUMTRY),A ;SET THE NUMBER OF TRIES TO ZERO. LD (CZSEEN),A ;Reset the control-Z seen flag LD A,'R' ;Get the state character LD (DISFLG),A ;Set the display flag CALL CONDCHR ;Display it as well CALL CLRPRT ;CLEAR OUT THE COMMUNICATIONS PORT STROUT HELPMSG CALL PROTO JP KERMIT ; ; This is the complete state ; COMP EQU $ LD DE,INFMS3 ;PUT IN "COMPLETE" MESSAGE. LD A,(CZSEEN) OR A ;... JR Z,COMP1 XOR A ;YES, CLEAR FLAG. LD (CZSEEN),A LD DE,INMS13 ;ISSUE "INTERRUPTED" MESSAGE. COMP1 LD A,(DISFLG) ;But only if we are supposed to OR A CALL NZ,FINMES ;PRINT COMPLETION MESSAGE JP KERMIT ; ; This is the abort state ; SABORT EQU $ LD DE,INFMS4 ;Message to print JR COMP1 ;Go print it conditionally ; ; Initialize the buffers, and clear the line ; INIT XOR A ;BUFFER SIZE. LD (CHRCNT),A ;NUMBER OF CHARS LEFT. LD HL,BUFF ;ADDR FOR BEGINNING. LD (BUFPNT),HL ;STORE ADDR FOR BEGINNING. CALL CLRPRT RET ; ; RECEIVE ROUTINES ; ; RECEIVE INIT with no previous file header ; RINIT CALL CHKTRYS ;Check retry threshold LD A,'1' ;RESET BLOCK CHECK TYPE TO SINGLE CHAR LD (CURCHK),A ;STORE AS CURRENT TYPE FOR INITIALIZATION CALL RPACK ;GET A PACKET. JP NAK ;TRASHED PACKET NAK, RETRY. JR RINIT_1 ; ; This entry point is for GET's. The file name is in DATA, and ; and 'R' packet will be sent out to ask for the file. ; RINITF CALL CHKTRYS ;Check retry threshold LD A,'1' ;START WITH SINGLE CHARACTER CHECKSUM LD (CURCHK),A ;SAVE THE TYPE LD A,(TEMP4) ;Get the length LD (ARGBLK+1),A ;Put it in the packet XOR A ;Start at packet zero LD (ARGBLK),A LD A,'R' ;Send RECV INIT CALL SPACK JP RECABORT ;Die if SEND fails LD A,'1' ;Reset the blk check type to 1 LD (CURCHK),A ;Store it CALL RPACK ;Get a packet JP QUIT ;Trashed, return to protocol JR RINIT_1 ;Join other code ; ; Common receive init code ; RINIT_1 EQU $ IFANOT 'S',RINIT3 ;Send initiate packet? LD A,(NUMTRY) ;GET THE NUMBER OF TRIES. LD (OLDTRY),A ;SAVE IT. XOR A LD (NUMTRY),A ;RESET THE NUMBER OF TRIES. LD A,(ARGBLK) ;RETURNED PACKET NUMBER. (SYNC THEM.) CALL INCPKT ;Increment the packet number CALL INCDISPKT LD A,(ARGBLK+1) ;GET THE NUMBER OF ARGUMENTS RECEIVED. LD HL,DATA ;GET A POINTER TO THE DATA. CALL SPAR ;GET THE DATA INTO THE PROPER VARIABLES. LD HL,DATA ;GET A POINTER TO OUR DATA BLOCK. CALL RPAR ;SET UP THE RECEIVE PARAMETERS. LD (ARGBLK+1),A ;STORE THE RETURNED NUMBER OF ARGUMENTS. LD A,'Y' ;ACKNOWLEDGE PACKET. CALL SPACK ;SEND THE PACKET. JP RECABORT ;FAILED, ABORT. LD A,(INICHK) LD (CURCHK),A ;FOR ALL FUTURE PACKETS NSTATE 'f' LD A,'F' CALL CONDCHR ;Display which packet RET RINIT3 IFANOT 'E',NAK_0 ;Is it a NAK ? CALL ERROR JP RECABORT ; ; THESE ARE SOME UTILITY ROUTINES. ; ; RECABORT ; RECABORT EQU $ LD IX,RTRANS ;Get the receive data area CALL UPDTRANS ;Update the transfer statics ABORT NSTATE 'A' ;Set state to abort ABORT_1 LD A,(LOGTRAN) ;Check if logging active CP 1 ;Is it on? RET NZ ;Return if not LD DE,TRFCB ;Get the FCB TRLOG TRANABRT,ABORT_2;Log the aborted message RET ;Return ; ; Close up after a tranaction log error ; ABORT_2 XOR A ;Reset the logging active flag LD (LOGTRAN),A LD DE,TRFCB ;Close the log file CALL XCLOSE RET ; ; SNDABORT ; SNDABORT NSTATE 'A' LD IX,STRANS CALL UPDTRANS JP ABORT_1 ; ; Nack a packet. ; NAK_0 XOR A ;Reset to first packet LD (PKTNUM),A ;Set the packet number JR NAK ;Join NAK code ; NAK_RTR CALL UPDRTR ;Update retries ; NAK LD A,(PKTNUM) ;GET THE PACKET NUMBER WE'RE WAITING FOR. LD (ARGBLK),A XOR A ;NO DATA. LD (ARGBLK+1),A LD A,'N' ;NAK THAT PACKET. CALL SPACK JP RECABORT ;GIVE UP. LD A,'N' ;Display NAKed character CALL CONDCHR RET ;GO AROUND AGAIN. ; ; Update the retry count ; UPDRTR EQU $ LD HL,(NUMRTR) INC HL ;INCREMENT THE NUMBER OF RETRIES LD (NUMRTR),HL RET ; ; THIS ROUTINE SETS UP THE DATA FOR INIT PACKET (EITHER THE ; SEND_INIT OR ACK PACKET). ; RPAR ADDPUT RPSIZ ;GET THE RECEIVE PACKET SIZE. ADDPUT STIME ;Add send timeout ADDPUT RPAD ;Add padding amount LD A,(RPADCH) ;Get the pad character ADD A,100O ;UNCONTROL IT. PUTHL A ;Put the pad character in ADDPUT REOL ;Put the end of line character LD A,(RQUOTE) ;GET THE QUOTE CHAR. PUTHL A LD A,(EBQFLG) ;Is eighth bit quoting on? IFZ RPAR1 ;If not, then say no PUTHL 'Y' ;Say yes to anything JR RPAR2 RPAR1 PUTHL 'N' ;Say no eighth bit quoting RPAR2 LD A,(INICHK) ;Check type PUTHL A LD A,(RPTQ) ;Get the repeat quote PUTHL A LD A,9 ;Nine pieces of data RET ; ; Tochar() A, and store indirect HL, then increment HL ; TCHPUT ADD A,' ' ;Tochar(A) PUTHL A ;Store it, and increment RET ;Return ; ; THIS ROUTINE READS IN ALL THE SEND_INIT PACKET INFORMATION. ; SPAR LD (TEMP4),A ;Save the number of arguments PUSH BC XOR A LD B,A LD (RPTFLG),A ;Set everything to default CALL CHKSPAR ;Check number of characters in packet LD A,(HL) ;Get THEIR Max packet size SUB 20H ;Make it real LD (SPSIZ),A ;Save the value CALL CHKSPAR ;Check the count GETHL A SUB 20H ;Make it real LD (RTIME),A ;Send packet timeout value CALL CHKSPAR ;Check the count GETHL A SUB 20H ;Make it real LD (SPAD),A ;Save the padding character CALL CHKSPAR ;Check the count of characters GETHL A ADD A,100O ;RE-CONTROLIFY IT. AND 7FH ;Keep us honest LD (SPADCH),A ;Save the padding character CALL CHKSPAR ;Check the count GETHL A SUB 20H ;Make it the real value LD (SEOL),A ;Save the value CALL CHKSPAR ;Check the count GETHL A LD (SQUOTE),A ;Save it CALL CHKSPAR ;Check the count INC HL LD A,(EBQFLG) IFZ SPAR7 LD A,(HL) IFA 'Y',SPAR4 IFANOT 'N',SPAR5 XOR A JR SPAR6 SPAR4 LD A,'&' SPAR5 LD (EBQ),A SPAR6 LD (EBQFLG),A SPAR7 CALL CHKSPAR ;Check the count GETHL A LD C,A ;COPY VALUE LD A,(CHKTYP) ;GET OUR TYPE IFA C,SPAR8 LD A,'1' ;NO, USE SINGLE CHARACTER SPAR8 LD (INICHK),A CALL CHKSPAR ;Check the count GETHL A IFA ' ',SPAR10 LD C,A LD (RPTQ),A ;Save it LD (RPTFLG),A SPAR10 EQU $ POP BC RET ;AND RETURN ; ; Check the count of characters left in the packet. ; CHKSPAR EQU $ LD A,(TEMP4) INC B CP B RET P POP HL ;Remove return address POP BC ;Restore original BC RET ;Return to caller ; ; RECEIVE FILE ; RFILE CALL CHKTRYS ;Check retry threshold CALL RPACK ;GET A PACKET. JP NAK ;TRASHED PACKET NAK, RETRY. IFANOT 'S',RFILE2 ;If not send init, then jump CALL CHKOLD ;Make sure we have not surpassed retries CALL CHKBLKDEC ;Check if previous packet number JP NZ,NAK_RTR ;No, NAK it, and try again CALL UPDRTR ;Update the retry count. LD HL,DATA ;Get the data address CALL RPAR ;Set up the parameter information LD (ARGBLK+1),A ;Save the number of bytes in the packet LD A,'Y' ;Acknowledge with parameters CALL SPACK ;Send the packet JP RECABORT ;Send failed, abort LD A,'S' ;Show the state as still send init CALL CONDCHR RET ; RFILE2 IFANOT 'Z',RFILE3 ;EOF packet? Jump if not CALL CHKOLD ;Check retry treshold CALL CHKBLKDEC ;Was it previous packet in sequence? JP NZ,NAK_RTR ;No, NAK it and try again CALL UPDRTR ;Update the number of retries XOR A ;Set length to zero LD (ARGBLK+1),A ;No data LD A,'Y' ;Send an ACK CALL SPACK ;Send the packet JP RECABORT ;Send failed, abort LD A,'Z' ;Show state as EOF CALL CONDCHR RET RFILE3 IFANOT 'F',RFILE4 ;Jump if not FILE header packet CALL CHKBLK ;Check packet number against current JP NZ,NAK_RTR ;If not the same, then NAK and try again CALL INCPKT ;Increment the packet number CALL INCDISPKT ;Increment the real packet count LD A,'F' LD (DISFLG),A ;Set the non-generic mode flag CALL CONDCHR ;Print the state character CALL GOFIL ;Get the file JP RECABORT ;Abort on an error CALL INIT ;Initialize everything else CALL NUM2OLD ;Reset the retry number LD (ARGBLK+1),A ;On return, A is zero, so NO DATA LD A,'Y' ;Send an ACK CALL SPACK ;Send the packet JP RECABORT ;Send failed, abort NSTATE 't' ;Set the state to receive transition LD A,(CZSEEN) ;Check if user requested EOF or EOT CP 'Z' ;Was it EOF? RET Z ;If it was EOF, then not yet XOR A ;Otherwise, must be EOT, so reset LD (CZSEEN),A ;Reset the flag RET ;And return, ignoring other states RFILE4 IFANOT 'B',RFILE5 ;Jump if not EOT CALL CONDCHR ;Display the state CALL CHKBLK ;Check packet number against current JP NZ,NAK_RTR ;If not right, then NAK and try again XOR A ;Set data length to zero LD (ARGBLK+1),A ;Store it for later LD A,'Y' ;Send an ACK CALL SPACK ;Send the packet JP RECABORT ;Send failed, abort NSTATE 'C' ;Set state to complete RET ;Return to caller RFILE5 CP 'X' ;Type on tty packet? JP NZ,BADERROR ;Bad packet if not CALL CHKBLK ;Make sure the packet number is right RET NZ ;Return if not CALL SETUPDIS ;Set up to type on terminal CALL PRTPKTOUT ;Print the packet contents CALL NEWLIN ;Get a newline CALL NUM2OLD ;Get new retry count LD (ARGBLK+1),A ;Zero length (A is zero on return) LD A,'Y' ;Send an ACK CALL SPACK ;Send the packet JP RECABORT ;Quit if send fails LD A,(PKTNUM) ;Get the packet number CALL INCPKT ;Add one CALL INCDISPKT ;Increment count for display NSTATE 'd' ;Set the state to receive data RET ;Return to protocol switch ; ; Transition between receive file, and receive data ; RECTRAN EQU $ STROUT KERREC ;Print the receiving message STROUT TFILNAM ;Print the name of the file LD A,(TRANLOG) ;Get the flag IFZ RTRAN_1 ;Test the flag and jump if not set LD DE,TRFCB ;Get the FCB TRLOG KERREC,RTRAN_3 ;Log the string TRLOG TFILNAM,RTRAN_3 ;Log the file name TRLOG TIMEMES,RTRAN_3 ;Log the time message CALL PRTTIME ;Print the current time RTRAN_1 EQU $ LD DE,FCB ;Get the file FCB address LD (RFIDCB),DE ;Save it as the output FCB CALL RSETPKT ;Reset the packet coding routines NSTATE 'd' ;Set the state to receive data RET ; ; Clean up on log file failure ; RTRAN_3 XOR A ;Clear A LD (TRANLOG),A ;Reset the logging flag LD DE,TRFCB ;Get the FCB CALL XCLOSE JR RTRAN_1 ;Ignore rest of logging code ; ; RECEIVE DATA ; RDATA CALL CHKTRYS ;Check the retry threshold CALL RPACK ;Get a packet JP NAK ;NAK it if bad packet IFANOT 'D',RDATA2 ;If not data check others RDAT11 CALL CHKBLK ;Check packet number against current JR Z,RDAT14 ;Jump if current packet CALL CHKOLD ;Check tries CALL CHKBLKDEC ;Check packet number against previous JP NZ,NAK_RTR ;Was not previous, so NAK it and retry CALL UPDRTR ;Update the number of retries XOR A ;Clear A LD (NUMTRY),A ;Reset the number of tries LD (ARGBLK+1),A ;Set the data length to zero LD A,'Y' ;Send ACK packet CALL SPACK ;Send the packet JP RECABORT ;Send failed, abort LD A,'%' ;Say we already saw this packet CALL CONDCHR ;and just stay in the same state RET ;Next packet RDAT14 CALL INCPKT ;Increment the packet number CALL INCDISPKT ;Increment the real packet count LD A,(NUMTRY) ;Get the number of retries LD (OLDTRY),A ;Save it LD A,(ARGBLK+1) ;Get the length of the data CALL PTCHR ;Decode the data packet and write it out JP RECABORT ;Can't write to output, abort XOR A ;Clear A LD (NUMTRY),A ;Reset the number of tries LD (ARGBLK+1),A ;Set data length to zero LD C,A ;Make C zero LD A,(CZSEEN) ;Check the flag IFZ RDAT15 ;If nothing, then skip LD C,A ;Get the character typed LD A,1 ;One data character LD (ARGBLK+1),A ;Set the length LD A,C ;Get the data character LD (DATA),A ;Store the character RDAT15 LD A,'Y' ;Send an ACK (Possibly with data) CALL SPACK ;Send the packet JP RECABORT ;Send failed, abort LD A,(NUMPKT) ;Time to log the progress? AND 3 ;Only every 4 packets RET NZ ;Return if not time LD A,'.' ;Get the character CALL CONDCHR ;Log it if not doing 'X' packet RET RDATA2 IFANOT 'F',RDATA3 ;File header? Jump if not CALL CHKOLD ;Check against previous retries CALL CHKBLKDEC ;Check packet number against previous JP NZ,NAK_RTR ;If not previous, then NAK and try again CALL UPDRTR ;Update the number of retries XOR A ;Clear A LD (NUMTRY),A ;Reset the number of retries LD (ARGBLK+1),A ;Set the length to zero LD A,'Y' ;Send an ACK CALL SPACK ;Send the packet JP RECABORT ;Send failed, abort LD A,'%' ;Already saw this one. CALL CONDCHR ;Tell the user RET RDATA3 CP 'Z' ;If not EOF then jump JP NZ,RDATA4 CALL CONDCHR ;Display the new state CALL CHKBLK ;Check packet number against current JP NZ,NAK_RTR ;If not, then NAK and try again CALL INCPKT ;Increment the packet number CALL INCDISPKT ;Increment the real packet count LD A,(ARGBLK+1) ;Get the length of the data IFANOT 1,RDAT35 ;Jump if packet length not 1 LD A,(DATA) ;Just one, get the data IFANOT 'D',RDAT36 ;Is it discard? Jump if not LD A,(TRANLOG) ;Check if loggin active IFZ RDAT31 LD DE,TRFCB ;Get the log file FCB TRLOG TRANCANC,RDAT39 ;Print canceled message RDAT31 LD A,(DISCARD) ;Check users preference for incompletes IFZ RDAT35 ;Jump if no discard CALL CHKFCB ;Is this FCB or *SO? JR NZ,RDAT36 ;Jump if no remove, and don't close either CALL XREMOVE ;Remove it JR Z,RDAT32 ;Jump if remove succeeded CALL XERROR0 ;Print system error message JR RDAT36 ;Join other code RDAT32 STROUT RMMES ;Print the message LD A,(TRANLOG) ;Check if loggin active IFZ RDAT36 LD DE,TRFCB TRLOG RMMES,RDAT39 JR RDAT36 ;Join the other code RDAT35 CALL CHKFCB ;Check for file FCB, don't close *SO CALL Z,XCLOSE ;Conditionally close the FILE RDAT36 XOR A ;Reset the EOF seen flag LD (CZSEEN),A CALL NUM2OLD ;Reset the number of retries LD (ARGBLK+1),A ;Set the length to zero LD A,'Y' ;Send an ACK CALL SPACK ;Send the packet JP RECABORT ;Send failed, abort NSTATE 'f' ;Set state to receive file LD IX,RTRANS ;Get the receive statistics address CALL UPDTRANS ;Update the transfer statistics RET ; ; Close up on a transaction log error ; RDAT39 XOR A ;Reset the logging flag LD (TRANLOG),A LD DE,TRFCB ;Close the file CALL XCLOSE JR RDAT36 ;Rejoin code ; RDATA4 CP 'X' ;Is it End Of Transmission? JP NZ,BADERROR ;If not, then bad packet CALL CHKBLKDEC ;Check if previous sequence number RET NZ ;Return if not XOR A ;Clear A LD (ARGBLK+1),A ;Set the length to zero LD A,'Y' ;Send an ACK CALL SPACK ;Send the packet JP RECABORT ;Send failed, abort RET ;Return to protocol ; ; Check received packet number against previous ; CHKBLKDEC EQU $ LD A,(PKTNUM) ;Get the current packet number DEC A ;Minus one for previous JR CHKBLK_1 ;Join other code ; ; Check the current packet number against that received ; CHKBLK EQU $ LD A,(PKTNUM) ;Get the current number CHKBLK_1 LD B,A ;Copy it to B LD A,(ARGBLK) ;Get the received packet number CP B ;Are they the same RET ;Return the condition codes ; ; Check for too many retries based on previous knowledge ; CHKOLD EQU $ LD A,(MAXTRY) ;Get the max number of tries LD B,A ;Save it LD A,(OLDTRY) ;Check against old max CP B ;Set the condition bits JR C,CHKOLD1 ;Jump if less than POP DE ;Remove the return address LD DE,ERMS10 ;Get the message CALL ERROR3 ;Display the error message JP RECABORT ;Change the state to abort CHKOLD1 INC A ;Increment the number of tries LD (OLDTRY),A ;Save the updated number of tries. RET ;Return normally ; ; Set up for a REMOTE command. The RFILE FCB is pointed at ; the *SO device, so that data received goes to the screen, ; rather than to a file. ; SETUPDIS EQU $ LD DE,(TMODCB) ;Get the current output DCB address LD (RFIDCB),DE ;Make it the current received file output XOR A ;Reset the 'display' flag LD (DISFLG),A CALL NEWLIN ;Get a fresh line RET ;Return to caller ; ; Conditionally display the string pointed to by DE based on the ; DISFLG which is active only during non REMOTE transactions. This ; makes REMOTE command pleasingly silent so that only the output ; of the requested operation is seen. ; CONDIS EQU $ PUSH AF ;Save A and the flags LD A,(DISFLG) ;Get the 'display' flag OR A ;Is it set? CALL NZ,PRTSTR ;If so, then print the string POP AF ;Restore the flags and A RET ;Return to caller ; ; Print the contents of the PACKET data area to the ; screen. ; PRTPKTOUT EQU $ LD HL,DATA ;Get the start of the string LD A,(ARGBLK+1) ;Get the length OR A RET Z ;Return if no data LD C,A ;Get the LSB into C LD B,0 ;Make BC a 16 bit offset ADD HL,BC ;HL is now the address past the end LD (HL),EOS ;Terminator for printing STROUT DATA JP NEWLIN ;Print a new line and return ; ; Update byte counters, IX MUST point to send or receive ; counter. We mod HL with 1K to get the remainder, and use ; the rest to sum into the current total. The remainder of ; HL mod 1024 is tucked away, but not forgotten. ; UPDTRANS EQU $ LD HL,(KTRANS) ;Calculate new total transfered LD C,(IX+2) ;Get the overflow counter LD B,(IX+3) ADD HL,BC ;Compute the total XOR A ;Reset the falg CALL C,ADD64K ;Add 64k if addition overflows LD A,H ;Get the high byte AND 3 ;Save the 2 lower order bits for mod 1024 LD B,A ;Put them in B LD C,L ;Put the other 8 bits into C LD (IX+2),C ;Store the new overflow (HL mod 1024) LD (IX+3),B LD A,H ;Trim to 1K multiple AND 0FCH ;A is now 4 times the number of Kbytes LD L,A ;Put it into L LD H,0 ;Make H zero SRL L ;Divide by 4 to align SRL L LD C,(IX) ;Get the total so far LD B,(IX+1) ADD HL,BC ;Compute the new total Kbyte LD (IX),L ;Put it back LD (IX+1),H ;ignoring any overflow CALL TRANSCNT ;Log the transaction size if logging LD HL,0 ;Set the counter to zero LD (KTRANS),HL LD (CURTRANS),HL ;Reset current counters LD (CURTRANS+2),HL RET ;Return to the caller ; ; Log the size of the last transaction to the logfile ; TRANSCNT EQU $ PUSH AF ;Save A and the FLAGS LD A,(TRANLOG) ;Is tranaction logging in progress? IFZ TRANSC_10 ;Jump if not active PUSH HL PUSH DE PUSH BC LD HL,(CURTRANS+2) ;Get the number of K transfered LD A,H OR L ;Is it zero? JR Z,TRANSC_3 ;Jump if it is CALL NUM2BUFF ;Put the number in the buffer LD DE,TRFCB ;Get the FCB address CALL OUTLOG ;Log the number of K transfered JP TRANSC_20 ;Close up on an error TRLOG KPLUS,TRANSC_20 ;Log the 'K + ' string TRANSC_3 EQU $ LD HL,(CURTRANS) ;Get the value CALL NUM2BUFF ;Make it printable LD DE,TRFCB ;Get the output FCB CALL OUTLOG ;Log the number of left over bytes JP TRANSC_20 ;Close up on an error TRLOG BYTESMES,TRANSC_20;Log the 'bytes transferred' message TRLOG TIMEMES,TRANSC_20; Log the time message CALL PRTTIME ;Print the current time TRANSC_9 EQU $ POP BC ;Restore the registers POP DE POP HL TRANSC_10 EQU $ POP AF ;Restore A and flags RET ;Return to caller TRANSC_20 EQU $ LD DE,TRFCB CALL XCLOSE XOR A LD (TRANLOG),A JP TRANSC_9 ; ; Convert binary to ascii, NO leading spaces ; NUM2BUFF EQU $ PUSH DE ;Save DE PUSH BC ;and BC LD DE,NBUFF ;Get the data buffer PUSH DE ;Save it for later CALL XHEXDEC EX DE,HL LD (HL),EOS ;Terminate the buffer POP HL ;Get the start back LD A,' ' ;Character to skip over N2B_1 EQU $ IFANOT (HL),N2B_2 ;Jump if passed last INC HL ;Point to next JR N2B_1 ;Back to test N2B_2 EQU $ POP BC ;Restore the registers POP DE RET ;Return to caller ;end of file <<< m4h191.asm >>> ; M4H191/ASM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Heath 19 terminal emulation filter ; ; Written By: Gregg Wonderly ; ; This program functions as a TRSDOS 6.2 device filter to emulate ; the h19 terminal. It recognizes most of the features of the ; H19 that are reasonable to implement on the Model 4. The items ; missing are ALT character set, and some of the [xy]n ; sequences. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This filter relocates itself to HIGH memory. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ORG 3000H TAB EQU 9 ;Tab character code ESC EQU 27 ;Tab character code S_OUT EQU 1 ;Screen on mask S_IN EQU 0FEH ;Screen off mask R_ON EQU 8 ;Reverse video on mask R_OFF EQU 0F7H ;Reverse video off mask FLAGVAL EQU 17 ;Flags offset from MODDCB SCR_MASK EQU 14 ;Offset of screen mask in flags WRINTMASK EQU 22 ;Interrupts mask in FLAGS BITOFFSET EQU 29 ; *GET M4H19/EQU ;Get the SVC equates *GET M4H19/MAC ;Get the macros ; ; The system enters the driver here with each character ; FILTER JR H19EMULATOR ;Go to the start of the driver DW 0 ;End of module address goes here DB 6 ;Length of the module name DB '$HEATH' ;The name MODDCB DW 0 ;To be filled in later DW 0 ;Filler VSCUR DB 95 ;Block cursor character VECUR DB 95 ;Underscore cursor character DEF_LEN DB 20 ;Default duration for the bell BELLFLAG DB 0 ;Visual or audible bell DEF_FREQ DW 125 ;Default frequency for bell tone OLDLOW DW 0 ;The address to restore if we ; remove ourselves OLDHIGH DW 0 ;This is where we are loaded at WHERE_AT DB 0 ;Flag for high or low mem load OFFSET DW 0 ;Offset from load to destination FVAL DB 0 ;No flags to start with BITVAL DW BITMASK ;Offset to 7-bit mask ; ; Start of actual Filter ; H19EMULATOR JR Z,ISPUT ;Go to process @PUT requests JP CHAIN_2 ;Ignore other options R002 EQU $-2 ; ; Do only @PUT requests ; ISPUT EQU $ LD A,@FLAGS ;Get the flags address into IY RST 28H LD A,C ;Character is in A and C now AND 07FH ;Strip any 8th bit if STRIP8 set BITMASK EQU $-FILTER-1 LD C,A LD (NEWCHAR),A ;Save the character to display R003 EQU $-2 LD HL,(OLDSTATE) ;Get any preexisting state R004 EQU $-2 LD A,H ;Check for on, NZ means yes OR L JR Z,NOSTATE ;Go if no state PUSH HL ;Put the address on the stack LD HL,0 ;Wipe out the state value LD (OLDSTATE),HL ;by storing zero in it R005 EQU $-2 RET ;Go to the address on the stack ; ; Look for what we should do with the character... ; NOSTATE LD A,C ;Get the character CP ESC ;Is it the escape character? JP Z,DOESCAPE ;Go do it if so R006 EQU $-2 CP ' ' ;Check for a Control Character JP C,DOCONTROL ;Go do it if so R007 EQU $-2 CALL INSERT_A ;Put the character on the screen R008 EQU $-2 JP RETOUT ;Return to caller R009 EQU $-2 ; ; Process all of the control characters between 0-31 inclusive ; DOCONTROL EQU $ LD A,(NEWCHAR) ;Get the character R010 EQU $-2 ADD A,A ;Times 2 for word offset LD C,A ;Get a copy of A for the offset LD B,0 ;Make BC a 16 bit offset LD HL,CTL_JMP_TBL ;Get the jump table R011 EQU $-2 ADD HL,BC ;Get the address in the table LD E,(HL) ;Get LSB of the address INC HL ;Point at next byte of address LD D,(HL) ;Get the MSB EX DE,HL ;Swap the jump address into HL LD A,H ;Is there a special routine? OR L ;Set the flags LD A,(NEWCHAR) ;Get the character back R012 EQU $-2 JP Z,RETOUT ;If not recognized, throw it out. R013 EQU $-2 JP (HL) ;Go to the special routine ; ; Control character jump table. Each word is the address of a ; routine that processes the specfic character. ; CTL_JMP_TBL DW 0,0,0,0,0,0,0 ;Throw these out. DW SET_BELL ;Start the buzzer. R014 EQU $-2 DW BACK_SPACE ;Backup a character NON-destruct. R015 EQU $-2 DW SHOW_TAB ;Skip a physical tab. R016 EQU $-2 DW LINE_FEED ;Down one line. R017 EQU $-2 DW 0 ;Throw this one out. DW FORM_FEED ;Clear the screen on FF. R018 EQU $-2 DW CARRIAGE ;Carriage return. R019 EQU $-2 DW 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;Not used. ; SET_BELL LD A,(BELLFLAG) ;Is the bell function valid? R020 EQU $-2 OR A JP Z,FLASH_SCREEN ;Flash if signaled R021 EQU $-2 LD A,(DEF_LEN) ;This is the timer value. R022 EQU $-2 LD L,A LD DE,(DEF_FREQ) R023 EQU $-2 BELL01 EQU $ LD A,1 OUT (90H),A LD B,D LD C,E BELL02 EQU $ DEC BC LD A,B OR C JR NZ,BELL02 XOR A OUT (90H),A LD B,D LD C,E BELL03 EQU $ DEC BC LD A,B OR C JR NZ,BELL03 DEC L JR NZ,BELL01 JP RETOUT ;Exit without chaining R024 EQU $-2 ; BACK_SPACE EQU $ LD A,24 ;Non-destructive backspace JP STORE_CHAIN ;Chain into any filters R025 EQU $-2 ; SHOW_TAB EQU $ GET_CURSOR ;Get the cursor position LD A,79 ;Last column to display in SUB L ;Compute the difference CP 8 ;Do we have enough? JP NC,TABOK ;If at least 8 then go do it R026 EQU $-2 LD A,29 ;Send simulated to *DO CALL CHAIN_IN R028 EQU $-2 LD A,26 JP CHAIN_IN ;No return R029 EQU $-2 TABOK EQU $ LD A,L ;Must truncate to even 8 chars ADD A,8 AND 0F8H LD L,A ;Get the column back into L NOSCROLL EQU $ PUT_CURSOR ;Set the cursor to what is in HL JP RETOUT ;Return R030 EQU $-2 ; LINE_FEED EQU $ LD A,26 ;Non-destructive LF CALL STORE_CHAIN ;Chain into any filters R031 EQU $-2 LD A,(FVAL) R131 EQU $-2 AND 2 ;Check for auto CR LD A,29 ;Get a CR CALL NZ,STORE_CHAIN R177 EQU $-2 JP RETOUT ;Return R178 EQU $-2 ; FORM_FEED EQU $ LD HL,0 ;Set the cursor to 0,0 PUT_CURSOR JP CLEAR_TO_EOS ;Do a clear to end of screen R032 EQU $-2 ; MOVE_HOME EQU $ LD HL,0 ;Get Row=0, Column=0 STORE_ROW_COL EQU $ PUT_CURSOR ;Move the cursor to the pos in HL JP RETOUT ;Return R033 EQU $-2 ; CARRIAGE EQU $ LD A,29 ;True carriage return CALL STORE_CHAIN R034 EQU $-2 LD A,(FVAL) R174 EQU $-2 AND 1 LD A,26 ;Get a line_feed CALL NZ,STORE_CHAIN ;Display it conditionally R175 EQU $-2 JP RETOUT R176 EQU $-2 ; ; Process the ESCAPE character sequences ; DOESCAPE EQU $ LD HL,ESCAPE_1 ;Set the next state to go to R035 EQU $-2 LD (OLDSTATE),HL R036 EQU $-2 JP RETOUT ;Leave with no chain R037 EQU $-2 ; ; Escape has been seen, now check for a special character ; ESCAPE_CHARS DB 'ABCDEFGHIJKLMNOY@fqpxyjkbol' ESC_LEN EQU $-ESCAPE_CHARS ; ESCAPE_1 EQU $ LD A,(NEWCHAR) ;Get the character sent R038 EQU $-2 LD HL,ESCAPE_CHARS ;Get the list of valid ones R039 EQU $-2 LD B,ESC_LEN ;Get how many LD DE,ESC_1_JMPS ;Get the vector table R040 EQU $-2 ESC_1_LOOP LD C,(HL) ;Get a character CP C ;Is it a match? JR Z,ESC_1_FND ;Found it, so go INC HL ;Next character INC DE ;next jump table entry INC DE DJNZ ESC_1_LOOP ;Loop while still more LD HL,0 LD (OLDSTATE),HL R041 EQU $-2 JP RETOUT ;Ignore unimplemented or invalid codes R042 EQU $-2 ; ESC_1_FND EQU $ EX DE,HL ;Get the vector's address LD E,(HL) ;Get the table value INC HL LD D,(HL) LD HL,0 ;Reset the state LD (OLDSTATE),HL R043 EQU $-2 EX DE,HL ;Get the vector in HL LD A,(NEWCHAR) R044 EQU $-2 JP (HL) ;Go do the right thing. ; ; Level 1 escape vector table ; ESC_1_JMPS DW CURSOR_UP R045 EQU $-2 DW LINE_FEED R046 EQU $-2 DW CURSOR_RIGHT R047 EQU $-2 DW BACK_SPACE R048 EQU $-2 DW FORM_FEED R049 EQU $-2 DW START_ALT_SET R050 EQU $-2 DW END_ALT_SET R051 EQU $-2 DW MOVE_HOME R052 EQU $-2 DW REV_INDEX R053 EQU $-2 DW CLEAR_TO_EOS R054 EQU $-2 DW CLEAR_TO_EOL R055 EQU $-2 DW ADD_LINE R056 EQU $-2 DW DEL_LINE R057 EQU $-2 DW DEL_CHAR R058 EQU $-2 DW END_INSERT R059 EQU $-2 DW SET_ESC_2 R060 EQU $-2 DW BEGIN_INSERT R061 EQU $-2 DW FLASH_SCREEN R062 EQU $-2 DW STAND_END R063 EQU $-2 DW STAND_OUT R064 EQU $-2 DW SET_ESC_2 R065 EQU $-2 DW SET_ESC_2 R066 EQU $-2 DW SAVE_CURSOR R001 EQU $-2 DW RESTORE_CURSOR R027 EQU $-2 DW ERA_BEG_SCR R141 EQU $-2 DW ERA_BEG_LIN R142 EQU $-2 DW ERASE_LINE R143 EQU $-2 ; ; Move the cursor up one line if possible, stopping at the top ; of the screen. ; CURSOR_UP EQU $ LD A,27 ;Non-destructive cursor up STORE_CHAIN EQU $ LD (NEWCHAR),A ;Store it R067 EQU $-2 JP CHAIN ;Let *DO do the dirty work R068 EQU $-2 ; CURSOR_RIGHT EQU $ LD A,25 ;Non-destructive cursor right JP STORE_CHAIN ;Let *DO do it for us R069 EQU $-2 ; START_ALT_SET JP RETOUT ;No defined action R070 EQU $-2 ; END_ALT_SET JP RETOUT ;No defined action R071 EQU $-2 ; ; This is the reverse scroll. We use direct screen access to ; move one line. Interrupts are off during the move, but are ; restored between each line. There seems to be quite reasonable ; behavior at 9600 baud with this strategy. ; REV_INDEX EQU $ GET_CURSOR ;Make sure we are at the top LD A,H ;Get the cursor row OR A ;Is it row zero? JP NZ,CURSOR_UP ;Go if not, to Cursor up routine R072 EQU $-2 LD A,15 ;Remove the cursor CALL CHAIN_IN R127 EQU $-2 LD A,23 ;Move 23 lines down LD HL,23*80+0F7FFH ;Get the next to last line, last byte LD DE,24*80+0F7FFH ;Get the last byte on the screen REV_LOOP LD BC,80 ;Get the byte count PUSH AF ;Save the line count SWAP_IN ;Screen in, interrupts off LDDR ;Move a line SWAP_OUT ;Screen out, interrupts on POP AF ;Get line count DEC A ;One less to move JR NZ,REV_LOOP ;Loop if not done REV_DONE EQU $ LD DE,SCR_BUFF ;Get the buffer address R073 EQU $-2 PUSH DE ;Save it PUSH DE ;Copy it into HL POP HL INC DE ;Point one ahead for the copy LD (HL),' ' ;Store one blank LD BC,79 ;Copy it into the remaining 79 LDIR ;Do the copy LD H,0 ;Get the top row POP DE ;Get the buffer address back PUT_LINE ;Put a blank line there LD A,14 ;Turn the cursor back on JP CHAIN_IN R074 EQU $-2 ; ; Flash the screen, by inverting all of the msb's of the characters ; twice. The result is a fair approximation to a flash. ; FLASH_SCREEN EQU $ LD A,16 ;Turn reverse video on CALL CHAIN_IN R128 EQU $-2 LD C,0 ;Get the loop counter FLASH_LOOP_1 EQU $ PUSH BC ;Save it LD H,0 ;Get the first line FLASH_LOOP_2 EQU $ LD DE,SCR_BUFF ;Get the buffer to put it in R075 EQU $-2 GET_LINE ;Get the line from @VDCTL PUSH HL ;Save the line number for PUT_LINE LD H,D ;Copy DE into HL LD L,E LD B,80 ;Get the BYTE count FLASH_LOOP_3 EQU $ LD A,(HL) ;Get a BYTE XOR 080H ;Invert the HIGH BIT LD (HL),A ;Put it back INC HL ;Point to the next DJNZ FLASH_LOOP_3 ;Loop until line is done POP HL ;Restore the Line number PUT_LINE ;Put the line back INC H ;Point to next line LD A,H ;Test for last CP 24 ;END? JR NZ,FLASH_LOOP_2 ;Loop if not done EI ;Make sure interrupts are back on POP BC ;Restore the FLASH counter LD A,C ;Get the original value INC C ;Increment the counter OR A ;Test OLD value JR Z,FLASH_LOOP_1 ;Loop if just finished first time LD A,17 ;Set reverse video OFF JP STORE_CHAIN ;Chain to *DO R076 EQU $-2 ; ; Save the current cursor position ; SAVE_CURSOR EQU $ LD DE,(LASTPUSH) ;Get the nextplace available R132 EQU $-2 GET_CURSOR ;Get the cursor EX DE,HL ;Swap push address for screen pos PUSH HL ;Save push address LD BC,ENDPUSH ;Get the first illeagal address R133 EQU $-2 OR A ;Reset the carry SBC HL,BC ;Compute difference POP HL ;Restore real address JR Z,NO_SAVE ;Jump if can't save LD (HL),E ;Put in column INC HL ;Point to next pos LD (HL),D ;Put in the row INC HL ;Point past it to next position LD (LASTPUSH),HL ;Save the new address R134 EQU $-2 NO_SAVE EQU $ JP RETOUT R135 EQU $-2 ; ; Restore the previously pushed cursor position. ; RESTORE_CURSOR EQU $ LD HL,(LASTPUSH) ;Get the next store position R136 EQU $-2 LD BC,PUSHAREA ;Get the start of the area R137 EQU $-2 OR A ;Reset carry PUSH HL ;Save the address SBC HL,BC ;See if anything to pop POP HL JR Z,NO_RESTORE ;Jump if not DEC HL ;Point back to row LD D,(HL) ;Get it DEC HL ;Point back to column LD E,(HL) ;Get it LD (LASTPUSH),HL ;Save the next position R138 EQU $-2 EX DE,HL ;Put the Row/Column into HL PUT_CURSOR ;Set the cursor position NO_RESTORE EQU $ JP RETOUT ;Return without calling *DO R139 EQU $-2 ; ; Erase the current line ; ERASE_LINE EQU $ GET_CURSOR ;Get the current position PUSH HL ;Save it LD L,0 ;Move to beginning of line PUT_CURSOR ;Store the new cursor position CALL CLEAR_TO_EOL R144 EQU $-2 POP HL PUT_CURSOR JP RETOUT R145 EQU $-2 ; ; Erase to beginning of screen ; ERA_BEG_SCR EQU $ GET_CURSOR ;Get the current screen position CALL GET_RC_ADDR ;Convert it to a memory address R146 EQU $-2 LD DE,0F800H ;Get the start of the screen OR A ;Reset the carry SBC HL,DE ;Compute number to blank LD B,H ;Put the count into BC LD C,L LD A,B ;See if at start of screen OR C JR Z,NO_ERA_SCR ;Jump if so, nothing to erase LD HL,0F800H ;Get the start LD DE,0F801H ;Get the start + 1 SWAP_IN ;Make the screen visible LD (HL),20H ;Blank one position SWAP_OUT ;Swap the screen back out DEC BC ;Decrement remaining places LD A,B ;See if only one needed blanking OR C JR Z,NO_ERA_SCR ;Jump it that was all SWAP_IN ;Swap the screen back in LDIR ;Blank the characters SWAP_OUT ;Swap the screen back out NO_ERA_SCR EQU $ JP RETOUT ;Return without chaining R147 EQU $-2 ; ; Clear to the beginning of the line ; ERA_BEG_LIN EQU $ GET_CURSOR ;Get current position PUSH HL ;Save it CALL GET_RC_ADDR ;Convert to memory address R148 EQU $-2 EX DE,HL ;Swap current to DE POP HL ;Get the row/column back LD L,0 ;Set row to start of screen CALL GET_RC_ADDR ;Get the address there R149 EQU $-2 EX DE,HL ;Swap it back OR A ;Reset the carry PUSH DE ;Save starting address SBC HL,DE ;Compute length LD B,H ;Put it into BC LD C,L LD A,B ;Check if no characters OR C JR Z,NO_ERA_LIN ;Jump if at start of line POP HL ;Get start of line address back LD D,H ;Make DE=HL+1 LD E,L INC DE SWAP_IN ;Swap the screen in LD (HL),20H ;Store a space SWAP_OUT ;Swap the screen out DEC BC ;Decrement the count for prev inst LD A,B ;Check for zero OR C ;Set the flags JR Z,NO_ERA_LIN SWAP_IN ;Fold the screen into memory LDIR ;Blank the screen SWAP_OUT ;Swap the screen back out NO_ERA_LIN EQU $ JP RETOUT ;Return to caller R150 EQU $-2 *GET M4H192/ASM END LOAD <<< m4h192.asm >>> ; M4H192/ASM CLEAR_TO_EOS EQU $ GET_CURSOR ;Get the cursor position CALL GET_RC_ADDR ;Get the real address R077 EQU $-2 PUSH HL ;Save the start for LDIR PUSH HL ;Copy it to BC POP BC LD HL,24*80+0F7FFH ;Get the last place to blank CLEAR_SPACE EQU $ OR A ;Reset the carry SBC HL,BC ;HL is now length of area PUSH HL ;Put it into BC and clear stack POP BC POP HL ;Get the starting address JR Z,NO_CLEAR ;Jump if no count PUSH HL ;Copy to DE POP DE INC DE ;Point DE one ahead PUSH BC ;Hide the cursor before PUSH DE PUSH HL LD A,15 ;Use *DO for this CALL CHAIN_IN R190 EQU $-2 POP HL ;Restore the stack POP DE POP BC SWAP_IN ;Swap screen into RAM LD (HL),' ' ;Store one blank SWAP_OUT CLR_LOOP LD A,30 ;One line max SWAP_IN ;Screen in LINE_LOOP PUSH AF ;Save the max counter LD A,B ;Check if done with all bytes OR C JR Z,END_CLEAR ;If done, exit POP AF ;Get the max count back LDI ;Blank one byte DEC A ;Decrement the max count JR NZ,LINE_LOOP ;If not done, do it again SWAP_OUT ;Swap the video out, and enable JR CLR_LOOP ;interrupts again, and loop. ; END_CLEAR POP AF ;Fix the stack SWAP_OUT ;Swap the video back out LD A,14 ;Turn the cursor back on JP CHAIN_IN R078 EQU $-2 NO_CLEAR EQU $ JP RETOUT R191 EQU $-2 ; CLEAR_TO_EOL EQU $ GET_CURSOR ;Get the cursor ROW/COL PUSH HL ;Save it CALL GET_RC_ADDR ;Get the ADDRESS equivilent R188 EQU $-2 EX (SP),HL ;Exchange for ROW/COL LD L,79 ;Point to end of this line CALL GET_RC_ADDR ;Get the RAM address R189 EQU $-2 POP BC ;Restore the beginning PUSH BC ;Save it LD A,C ;If C = L then at EOL CP L JR Z,NO_CLEAR ;So skip rest of operations JR CLEAR_SPACE ; DEL_CHAR EQU $ LD DE,SCR_BUFF ;Get the buffer address R079 EQU $-2 PUSH DE ;Save it for the store GET_CURSOR ;Get the row to retrieve PUSH HL ;Save the column for later store GET_LINE ;Get the line into the buffer LD A,79 ;Maximum characters to move SUB L ;Subtract the current position LD H,0 ;Set the column to zero ADD HL,DE ;HL is now the place to start at PUSH HL ;Get a copy in de POP DE OR A JR Z,NO_D_CHAR LD C,A ;Get the count in BC as 16 bits LD B,0 INC HL ;Move the source one forward LDIR ;Skoot it all backwards NO_D_CHAR EQU $ LD A,' ' ;Get a space character LD (DE),A ;Blank the last space on the line POP HL ;Get the row to store at POP DE ;Get the buffer address back PUT_LINE ;Put the line back on the screen JP RETOUT R080 EQU $-2 ; END_INSERT EQU $ XOR A LD (INSERT_FLAG),A ;End insert mode R081 EQU $-2 JP RETOUT R082 EQU $-2 ; BEGIN_INSERT LD A,1 LD (INSERT_FLAG),A ;Begin insert mode R083 EQU $-2 JP RETOUT R084 EQU $-2 ; STAND_END EQU $ LD A,17 ;End standout mode JP STORE_CHAIN R085 EQU $-2 ; STAND_OUT EQU $ LD A,16 JP STORE_CHAIN ;Begin standout mode R086 EQU $-2 ; ; At this point, there are still more characters to distinguish ; between sequences. So we set the next state to go to ; SET_ESC_2 EQU $ LD HL,ESCAPE_2 ;Get address of the next state R087 EQU $-2 LD (OLDSTATE),HL ;Save it R088 EQU $-2 LD A,(NEWCHAR) ;Get the character sent this time R089 EQU $-2 LD (CHAR_2),A ;Save the character R090 EQU $-2 JP RETOUT ;Skip the *do device and return R091 EQU $-2 ; ; Jump table for processing ESC-y-[123456789] and ESC-x-[123456789] ; sequences ; MODE_TABLE EQU $ DW ENABLE_25TH R153 EQU $-2 DW NO_KEY_CLICK R154 EQU $-2 DW HOLD_SCREEN R155 EQU $-2 DW BLOCK_CURSOR R156 EQU $-2 DW CURSOR_OFF R157 EQU $-2 DW KEYPAD_SHIFTED R158 EQU $-2 DW ALT_KEY_MODE R159 EQU $-2 DW AUTO_LF R160 EQU $-2 DW AUTO_CR R161 EQU $-2 DW DISABLE_25TH R162 EQU $-2 DW KEY_CLICK R163 EQU $-2 DW NO_HOLD_SCREEN R164 EQU $-2 DW LINE_CURSOR R165 EQU $-2 DW CURSOR_ON R166 EQU $-2 DW KEY_UNSHIFT R167 EQU $-2 DW EXIT_ALT_KEY R168 EQU $-2 DW NO_AUTO_LF R169 EQU $-2 DW NO_AUTO_CR R170 EQU $-2 ; ; Process third character in 3 character or more sequence ; ESCAPE_2 EQU $ LD A,(CHAR_2) ;Get the previous character R092 EQU $-2 CP 'x' ;Was it options on JR Z,OPTION_X ;Yep, go do it CP 'y' ;Was it options off? JR NZ,MOVE_CURSOR ;Jump if not LD C,18 ;Get the offset JR OPTIONS ;Join other code OPTION_X EQU $ LD C,0 ;Get offset at zero OPTIONS EQU $ LD A,(NEWCHAR) ;Get the character R130 EQU $-2 SUB '1' ;Zero base it CP 9 ;Check for too big JP NC,RETOUT ;Can't do this one R187 EQU $-2 CP 0 JP C,RETOUT R171 EQU $-2 SLA A ;Multiply by 2 ADD A,C ;Tack on offset LD C,A ;Make BC a 16 bit offset LD B,0 LD HL,MODE_TABLE ;Get the table R172 EQU $-2 ADD HL,BC LD E,(HL) ;Get the low order byte INC HL ;Point to MSB LD D,(HL) ;Get the MSB PUSH DE ;Put it on the stack RET ;Jump to it ; ; All of the following options are not implemented, so they are ; ignored ; ENABLE_25TH: NO_KEY_CLICK: HOLD_SCREEN: KEYPAD_SHIFTED: ALT_KEY_MODE: DISABLE_25TH: KEY_CLICK: NO_HOLD_SCREEN: EXIT_ALT_KEY: KEY_UNSHIFT: GOOUT EQU $ JP RETOUT R173 EQU $-2 ; AUTO_LF EQU $ LD A,(FVAL) R179 EQU $-2 OR 1 LD (FVAL),A R180 EQU $-2 JR GOOUT ; AUTO_CR EQU $ LD A,(FVAL) R181 EQU $-2 OR 2 LD (FVAL),A R182 EQU $-2 JR GOOUT ; NO_AUTO_LF EQU $ LD A,(FVAL) R183 EQU $-2 AND 0FEH LD (FVAL),A R184 EQU $-2 JR GOOUT ; NO_AUTO_CR EQU $ LD A,(FVAL) R185 EQU $-2 AND 0FDH LD (FVAL),A R186 EQU $-2 JR GOOUT ; BLOCK_CURSOR EQU $ LD HL,(VIDEO_START);Get the call out vector R093 EQU $-2 CHECK_JUMP LD A,H ;Check for valid OR L JP Z,RETOUT ;Jump if no address specified R094 EQU $-2 LD DE,RETOUT ;Push the return address R095 EQU $-2 PUSH DE JP (HL) ;Call the users routine CURSOR_ON EQU $ LD A,15 ;Cursor on to *DO JP STORE_CHAIN R151 EQU $-2 ; LINE_CURSOR EQU $ LD HL,(VIDEO_END) ;Get the vector R096 EQU $-2 JR CHECK_JUMP ; CURSOR_OFF EQU $ LD A,14 JP STORE_CHAIN R152 EQU $-2 ; MOVE_CURSOR EQU $ LD A,(NEWCHAR) R097 EQU $-2 SUB ' ' ;This should be the row JP C,RETOUT ;Abort if bad row R098 EQU $-2 CP 24 ;check for too big JP NC,RETOUT ;Abort on bad here too R099 EQU $-2 LD (GOTO_ROW),A ;Save the row R100 EQU $-2 ; ; Now we must wait for the column to get here, so set the state, ; LD HL,ESCAPE_3 ;Set the state for column R101 EQU $-2 LD (OLDSTATE),HL ;Store it R102 EQU $-2 CONTINUE EQU $ JP RETOUT ;Chain into any filters R103 EQU $-2 ; ; At this point, we are looking for the column of a cursor ; motion sequence. This is the longest sequence ; ESCAPE_3 LD A,(NEWCHAR) ;Get the character R104 EQU $-2 SUB ' ' ;Get rid of the bias JP C,RETOUT ;Abort if bad column R105 EQU $-2 CP 80 ;Check for too high JP NC,RETOUT ;Exit if over R106 EQU $-2 LD L,A ;Get the column in L LD A,(GOTO_ROW) ;Get the ROW from the save area R107 EQU $-2 LD H,A ;Put it in HL for PUT_CURSOR PUT_CURSOR ;Set the new cursor position JP RETOUT ;Return R108 EQU $-2 ; DEL_LINE LD A,1 ;Set the delete line flag JR LINE_OPS ; ADD_LINE XOR A ;Clear the flag ; ; The following code is somewhat shared by the INSERT and DELETE ; line code. This code accesses the video memory directly to get ; the fastest possible movement. Interrupts must be off while ; the screen is swapped in, so a compromise was made so that the ; interrupts were not off for too long. The movement of the ; screen is done one line at a time. Interrupts are turned back ; on in between lines, so that the UART can generate RECEIVED ; CHARACTER AVAILABLE interrupts. I have had reasonable behavior ; at 9600 BAUD with this idea... ; LINE_OPS LD (DEL_FLAG),A ;Store the flag value R109 EQU $-2 GET_CURSOR ;Get the current row and column LD A,23 ;Get the maximum possible SUB H ;Get the difference in rows JR Z,CLEAR_LINE ;Go clear the line if on the last PUSH IY PUSH HL ;Save HL from the call to *DO PUSH BC PUSH DE PUSH AF LD A,15 ;Turn the cursor off CALL CHAIN_IN ;Call *DO to do the work R129 EQU $-2 POP AF POP DE POP BC POP HL ;Restore the ROW/COL POP IY LD A,(DEL_FLAG) ;Get the flag R110 EQU $-2 OR A JR Z,INS_MODE ; ; Delete the line that the cursor is on ; PUSH HL ;Save the row and column LD L,0 ;Go to the first col of the line CALL GET_RC_ADDR ;Get the effective address in mem R111 EQU $-2 POP AF ;Get the row in A, ignoring F PUSH HL ;Move the address to DE POP DE LD BC,80 ;One row is this many characters ADD HL,BC ;Add one row to HL for the source DEL_LOOP EQU $ SWAP_IN ;Swap the screen into view PUSH BC LDIR ;Move one rows worth POP BC SWAP_OUT ;Swap the screen back out INC A ;Add one to the row CP 23 ;Are we at the end? JR NZ,DEL_LOOP ;Loop if not LD H,A ;Load H with the last row JR LINE_OPS_1 ;Join the other code ; INS_MODE EQU $ LD A,23 ;Max lines on a screen SUB H ;Minus current line = remaining LD HL,23*80+0F7FFH ;Source address for LDDR LD DE,24*80+0F7FFH ;Destination address for LDDR LD BC,80 ;Number of bytes to move INS_LOOP EQU $ SWAP_IN ;Swap the screen in PUSH BC LDDR ;Move one line POP BC SWAP_OUT ;Swap the screen out DEC A ;Decrement the line count JR NZ,INS_LOOP ;Loop until done CLEAR_LINE EQU $ GET_CURSOR ;Get the current row LINE_OPS_1 EQU $ PUSH HL ;Save the row LD DE,SCR_BUFF ;Get the buffer address R112 EQU $-2 PUSH DE ;Save the buffer address PUSH DE ;Copy the address into hl POP HL INC DE ;Plus one for the copy LD BC,79 ;Copy 79 times LD (HL),' ' ;Store one blank LDIR ;Copy in the rest POP DE ;Restore the buffer address POP HL ;Restore the row PUT_LINE ;Put the line back LD A,14 ;Turn the cursor back on JP CHAIN_IN R113 EQU $-2 ; ; Chain into any filters ; CHAIN EQU $ LD A,(NEWCHAR) ;Get the character sent to us R114 EQU $-2 CHAIN_IN EQU $ LD C,A ;Move the character to C for @PUT LD B,2 ;Signal @PUT for others in chain OR A ;Reset the carry CP A ;Set Z flag CHAIN_2 EQU $ PUSH IX ;Save the old DCB address LD IX,(MODDCB) ;Get the next in chain R115 EQU $-2 LD A,@CHNIO RST 28H POP IX ;Restore the old ; ; Return without knowldege of the call to *DO ; RETOUT EQU $ LD A,(NEWCHAR) ;Get the character sent R125 EQU $-2 CP A ;Set the Z flag RET ; ; Clear the screen ; CLEAR_SCREEN EQU $ LD HL,0 ;Put the cursor at the top PUT_CURSOR JP CLEAR_TO_EOS R126 EQU $-2 ; ; Put the character in A on the screen at the current screen ; position. If insert mode is active, then perform the shift ; of the line before chaining to *DO which will do the actual ; displaying for us. ; INSERT_A EQU $ PUSH AF ;Save the character GET_CURSOR ;Get the cursor position PUSH HL ;Save the cursor position LD A,(INSERT_FLAG) ;Get the insert mode flag R116 EQU $-2 OR A ;Is insert character mode on? JR Z,NO_MOVE ;Jump if no insert character mode LD DE,SCR_BUFF ;Get the buffer's address R117 EQU $-2 GET_LINE ;Get the line from the screen LD A,79 ;Get the maximum to move SUB L ;Compute the number to move LD C,A ;Make the byte, 16 bits in BC LD B,0 ;Zero the high byte for 16 bits OR A ;Check if count is already zero JR Z,NO_MOVE ;Skip if it is LD L,79 ;Get the end of the buffer LD H,0 ; by adding 79 to the address ADD HL,DE ;HL is now the end of the buffer PUSH DE ;Save the buffer address LD E,L ;Copy HL to DE LD D,H DEC HL ;Decrement the source address LDDR ;Skoot the line over POP DE ;Restore the buffer address POP HL ;Restore the row to restore PUT_LINE ;Put it on the screen PUSH HL ;Push something for the POP NO_MOVE EQU $ POP HL ;Restore the current row/col POP AF ;Restore the character to insert JP CHAIN ;Use *DO to display it R118 EQU $-2 ; ; The default visual begin command is to change the cursor ; to a block character ; VSTART EQU $ LD B,8 ;Change cursor character LD A,(VSCUR) ;Get the video start cursor R119 EQU $-2 LD C,A ;Special graphics block LD A,@VDCTL RST 28H RET ; ; This is the default call out for visual end. ; VEND EQU $ LD B,8 ;Set the normal cursor character LD A,(VECUR) ;Get the video end cursor R120 EQU $-2 LD C,A LD A,@VDCTL RST 28H RET ;Return ; ; ; Calculate address of Row and Column in HL ; GET_RC_ADDR PUSH BC PUSH AF PUSH DE PUSH HL ;Copy the Row and Column to DE POP DE LD HL,0F800H ;Get the start of the screen LD BC,80 ;One row is this long ADD_LOOP DEC D ;Decrement the row count JP M,NO_MORE ;If less than zero, no more rows R121 EQU $-2 ADD HL,BC ;Add one more Row's worth JR ADD_LOOP ;Go to the top of the loop NO_MORE LD D,0 ;Make it a 16 bit value ADD HL,DE ;Add it into the total POP DE POP AF POP BC RET ;Return to caller ; ; Calculate Row and Column based on address in HL ; GET_ADDR_RC PUSH BC ;Save the registers PUSH AF PUSH DE LD BC,0F800H ;Get the start of the screen OR A ;Reset the carry flag SBC HL,BC ;HL now is the offset into screen LD D,0 ;This is the counter LD BC,80 ;Get one rows worth SUB_LOOP OR A ;Reset the carry SBC HL,BC ;Subtract one rows worth JP C,NO_MORE_2 ;There are no more so leave R122 EQU $-2 INC D ;Add one to the row count JR SUB_LOOP ;Go to the top of the loop NO_MORE_2 ADD HL,BC ;Correct for the subtract LD H,D ;Get the row count, L has the ;Column already in it POP DE ;Restore the registers POP AF POP BC RET ;Return to the caller ; ; Data storage area ; LASTPUSH DW PUSHAREA ;Next place to push pos into R140 EQU $-2 PUSHAREA DS 20 ;Storage area ENDPUSH EQU $ ;End of storage OLDSTATE DW 0 ;Any preexisting state for ;special character sequences, ;actually, the address of the ;routine to execute the next time ;that a @PUT request is made. INSERT_FLAG DB 0 ;Insert character mode flag DEL_FLAG DB 0 ;Delete or Insert line direction CHAR_2 DB 0 ;Second character in a multiple ; ;character sequence. VIDEO_START DW VSTART ;Call out address for visual begin R123 EQU $-2 VIDEO_END DW VEND ;Call out address for visual end R124 EQU $-2 FLAG_ADDR DW 0 ;Address of flags area GOTO_ROW DB 0 ;Saved row for cursor motion SCR_BUFF DS 81 ;Space for put_line and get_line NEWCHAR DB 0 ;Character sent to @PUT request MODEND EQU $ ;End of the routine FLTR_LEN EQU MODEND-FILTER ;This is the length INTRO EQU $ DB 'H19 Emulator-filter for TRSDOS 6.2. ' DB 'Written by: Gregg Wonderly',29,26 DB 'Load address: ',3 INTRO2 DB ' Ending address: ',3 STRING DS 80 FIRST DW 0 ; ; Entry point of load routine. ; LOAD EQU $ LD (MODDCB),DE ;Save the DCB address LD A,@FLAGS ;Get the Flags area address RST 28H LD (FLAG_ADDR),IY ;Save it away LD HL,INTRO ;Print the intro message LD A,@DSPLY RST 28H LD HL,0 ;Get HIGH MEMORY pointer from DOS LD B,0 ;B=0 selects HIGH$ LD A,@HIGH$ RST 28H LD (OLDLOW),HL ;Save it for later restoral LD (FILTER+2),HL PUSH HL ; ; Since this filter accesses the video directly, we can not reside ; up where it does. Here we determine if there is suffient space ; used to put us below the screen, or that we must waist memory, ; and relocate to just below 0F400H. ; LD HL,0F3FEH ;Get the highest usable address POP BC ;Get the old HIGH memory OR A ;Reset the carry bit PUSH HL ;Save HL SBC HL,BC ;See if hl is less than bc POP HL ;Get HL back JR C,USE_HL ;If C, then use HL's address PUSH BC ;Move BC into HL POP HL USE_HL EQU $ INC HL ;Must increment for true value LD BC,FLTR_LEN ;Get the length of the filter OR A ;Reset the carry SBC HL,BC ;Compute the new high PUSH HL ;Save where to load at DEC HL ;One below that is new high LD (OLDHIGH),HL ;Save it for restore when removed LD B,0 ;Select HIGH$ LD A,@HIGH$ RST 28H RELOCATE EQU $ ; ; THIS ROUTINE WILL MOVE THE FILTER, UP INTO HIGH MEMORY AND ; RESET THE POINTER TO HIGH$ ; POP DE ;Get the load address LD (FIRST),DE ;Save it for later LD HL,STRING ;Get the scratch area PUSH HL ;Save the address for @DSPLY LD A,@HEX16 ;Convert DE to 4 HEX digits (HL) RST 28H LD (HL),3 ;Terminate with ETX POP HL ;Get the start LD A,@DSPLY ;Display it RST 28H LD HL,(FIRST) ;Get the starting reloc address LD BC,FILTER ;Calculate offset from source OR A ;Reset the carry PUSH HL ;Save it SBC HL,BC ;Offset now in HL LD (OFFSET),HL ;Save it for later reference POP HL ;Get the load address into hl LD BC,FLTR_LEN ;Calculate the end ADD HL,BC ;HL now has the ending address PUSH HL ;Save it for transfer to DE LD HL,INTRO2 ;Get the message string LD A,@DSPLY ;Display it RST 28H POP DE ;Get the ending address LD HL,STRING ;Get the string buffer PUSH HL ;Save the address for later LD A,@HEX16 ;Convert DE to 4 HEX digits (HL) RST 28H LD (HL),13 ;Put a carriage return on the end POP HL ;Get the starting address back LD A,@DSPLY ;Display the VALUE RST 28H LD IX,OFFTBL ;Get start of offset table ; ; LOOP TO ADD OFFSET TO ALL ADDRESSES NECESSARY ; MOVNXT EQU $ LD BC,(OFFSET) ;Put the offset into BC LD L,(IX) ;Get LSB of address to change INC IX ;POINT TO MSB LD H,(IX) ;GET IT INC IX ;POINT TO LSB OF NEXT, OR END PUSH IX ;Save pointer to table PUSH HL ;Put the address into IX POP IX LD L,(IX) ;Get the LSB for relocation LD H,(IX+1) ;Get the MSB ADD HL,BC ;Relocate it LD (IX),L ;Put it back LD (IX+1),H POP BC ;Get the table address in BC PUSH BC ;Copy it back into IX POP IX ;Restore the table address LD HL,OFFEND ;Get the end of the offset table OR A ;Reset the carry SBC HL,BC ;Compute the difference JR NZ,MOVNXT ;Loop, if not done ; LD BC,FLTR_LEN ;MOVE MODULE INTO HIGH MEMORY. LD DE,(FIRST) LD HL,FILTER ;Get the load address LDIR ;Move it into place LD IX,(MODDCB) ;Get the dcb address back LD DE,(FIRST) LD (IX),47H ;Say we are a filter LD (IX+1),E ;Tell where the filter starts LD (IX+2),D LD HL,0 CP A RET ; OFFTBL EQU $ DW R001 DW R002 DW R003 DW R004 DW R005 DW R006 DW R007 DW R008 DW R009 DW R010 DW R011 DW R012 DW R013 DW R014 DW R015 DW R016 DW R017 DW R018 DW R019 DW R020 DW R021 DW R022 DW R023 DW R024 DW R025 DW R026 DW R027 DW R028 DW R029 DW R030 DW R031 DW R032 DW R033 DW R034 DW R035 DW R036 DW R037 DW R038 DW R039 DW R040 DW R041 DW R042 DW R043 DW R044 DW R045 DW R046 DW R047 DW R048 DW R049 DW R050 DW R051 DW R052 DW R053 DW R054 DW R055 DW R056 DW R057 DW R058 DW R059 DW R060 DW R061 DW R062 DW R063 DW R064 DW R065 DW R066 DW R067 DW R068 DW R069 DW R070 DW R071 DW R072 DW R073 DW R074 DW R075 DW R076 DW R077 DW R078 DW R079 DW R080 DW R081 DW R082 DW R083 DW R084 DW R085 DW R086 DW R087 DW R088 DW R089 DW R090 DW R091 DW R092 DW R093 DW R094 DW R095 DW R096 DW R097 DW R098 DW R099 DW R100 DW R101 DW R102 DW R103 DW R104 DW R105 DW R106 DW R107 DW R108 DW R109 DW R110 DW R111 DW R112 DW R113 DW R114 DW R115 DW R116 DW R117 DW R118 DW R119 DW R120 DW R121 DW R122 DW R123 DW R124 DW R125 DW R126 DW R127 DW R128 DW R129 DW R130 DW R131 DW R132 DW R133 DW R134 DW R135 DW R136 DW R137 DW R138 DW R139 DW R140 DW R141 DW R142 DW R143 DW R144 DW R145 DW R146 DW R147 DW R148 DW R149 DW R150 DW R151 DW R152 DW R153 DW R154 DW R155 DW R156 DW R157 DW R158 DW R159 DW R160 DW R161 DW R162 DW R163 DW R164 DW R165 DW R166 DW R167 DW R168 DW R169 DW R170 DW R171 DW R172 DW R173 DW R174 DW R175 DW R176 DW R177 DW R178 DW R179 DW R180 DW R181 DW R182 DW R183 DW R184 DW R185 DW R186 DW R187 DW R188 DW R189 DW R190 DW R191 OFFEND EQU $ <<< m4h19s.asm >>> ; M4H19S/ASM *GET M4H19/EQU *GET M4H19/MAC VS EQU 15 ;Offset in header for visual cursor VE EQU 16 ;Offset in header for line mode cursor DEF_LEN EQU 17 ;Default length of audible bell BELLFLAG EQU 18 ;Audible or visual bell flag DEF_FREQ EQU 19 ;Frequency value for bell tone OLDLOW EQU 21 ;Set up address used for removing *HP OLDHIGH EQU 23 ;Ditto BIT_MASK EQU 29 ;Offset to bit mask ; ; Load in low memory to avoid user programs, and KERMIT in ; particular ; ORG 2500H START: LD DE,ARGBUFF+1 ;Copy the arguments LD BC,255 ;Pick a number suffiently large LD (PARMS),DE ;Save the dest for later use LDIR ;Move the command line GETH19: LD DE,H19_NAME ;Check to see if $HEATH is there SSVC @GTMOD ;Try to find it JP NZ,NOH19 ;Not there, so go put it in PUSH HL ;Put the header address into IX POP IX LD DE,PARAM_TABLE ;Get the parameter table LD HL,(PARMS) ;Get the command line ; ; We look for a '(' to know whether or not to display the usage ; message. If we do not find one, then we give the user help. ; LOOP1: LD A,(HL) ;See if there is anything there CP 13 ;End of command line JP Z,SHOW_VALS ;If so, then give help CP '(' ;Start of argument list? JR Z,LOOP2 ;Jump if it is INC HL ;Point to next JR LOOP1 ;Loop on LOOP2: DEC HL ;Back up before the '(' SSVC @PARAM ;Parse the parameter list JP NZ,SHOW_VALS ;On failure, give help LD A,(RESP_VS) ;Was a BLOCK cursor value given? OR A JR Z,CHK_VE ;Jump if not AND 60H ;Verify only numeric. JP NZ,BAD_PARAM ;Jump if not LD HL,(VS_VAL) ;Get the value given LD A,H ;Make sure it is only a byte OR A JP NZ,TOO_BIG ;Print a message if too big LD A,L ;Get the byte value from L LD (IX+VS),A ;Save it into the $HEATH header CHK_VE: LD A,(RESP_VE) ;Was there a line mode cursor OR A ;Jump if not JR Z,CHK_REM AND 60H ;Verify it is only numeric JP NZ,BAD_PARAM ;Jump if bad LD HL,(VE_VAL) ;Get the value LD A,H ;Make sure it is a byte value OR A JP NZ,TOO_BIG ;Jump if too big. LD A,L ;Get the byte value from L LD (IX+VE),A ;Store it CHK_REM: LD A,(RESP_REMOVE) ;Is this a remove request? OR A JR Z,CHK_FREQ ;If not go check bell frequency AND 0A0H ;Must be boolean JP NZ,BAD_PARAM LD B,0 ;Get the current HIGH$ value LD HL,0 SSVC @HIGH$ JP NZ,ERROR LD A,(IX+OLDHIGH) ;Get the OLD HIGH$ from header LD C,A LD A,(IX+OLDHIGH+1) LD B,A ;See if they are still the same OR A ;Reset the carry SBC HL,BC ;Compute the difference JP NZ,CANT_REMOVE ;If not equal, then can't remove LD A,(IX+OLDLOW) ;Get the previous HIGH$ that was LD L,A ;in effect before $HEATH was LD A,(IX+OLDLOW+1) ;installed LD H,A LD B,0 ;removing the module SSVC @HIGH$ JP NZ,ERROR ; ; The code here make several RASH assumptions about what devices ; $HEATH is mated to. It assumes that the following commands were ; used to install the $HEATH module: ; ; set *hp h19 ; filter *so *hp ; ; With these in mind, it does the following commands ; ; reset *so ; reset *hp ; remove *hp ; route *so *do ; ; This should restore the system to a reasonable state, given the ; fact that the filter should be in by itself anyway. ; REMOVE_FILTER: LD HL,CMD1 ;Do "reset *so" command SSVC @CMNDR LD HL,CMD2 ;Do "reset *hp" command SSVC @CMNDR LD HL,CMD3 ;Do "remove *hp" command SSVC @CMNDR LD HL,CMD4 ;Do "route *so *do" command SSVC @CMNDR JP SET_EXIT ;Nothing else is reasonable, quit CHK_FREQ: LD A,(RESP_FREQ) ;Check for a frequency given OR A JR Z,CHK_DUR ;Jump if none there AND 60H ;Verify that it is numeric JP NZ,BAD_PARAM ;Jump if not just numeric LD HL,(FREQ_VAL) ;Get the value LD (IX+DEF_FREQ),L ;Use all 16 bits worth LD (IX+DEF_FREQ+1),H CHK_DUR: LD A,(RESP_DURA) ;Is there a duration given? OR A JR Z,CHK_BELL ;Jump if there is isn't AND 60H ;Verify that it is numeric JP NZ,BAD_PARAM ;Jump if it is not LD HL,(DUR_VAL) ;Get the value LD A,H ;Make sure there is only a byte OR A JP NZ,TOO_BIG ;Jump if MSB not zero LD A,L ;Get the byte value from L LD (IX+DEF_LEN),A ;Save the tone length CHK_BELL: LD A,(RESP_BELL) ;Are they setting bell flag? OR A JP Z,CHK_STRIP8 ;Check if strip8 parameter given AND 0A0H ;Is it boolean? JP NZ,BAD_PARAM ;Jump if not LD A,(BELL_VAL) ;Get the value LD (IX+BELLFLAG),A ;Save it CHK_STRIP8: LD A,(RESP_STRIP8) ;Get the parameter present flag OR A JP Z,CHK_SHOW ;Go check show parameter AND 0A0H ;Check if boolean JP NZ,BAD_PARAM LD C,(IX+BIT_MASK) LD B,(IX+BIT_MASK+1) PUSH IX POP HL ADD HL,BC ;Compute the offset LD C,0FFH ;Get the off mask LD A,(STRIP8_VAL) OR A JR Z,STRIP8_OFF ;Option is off so jump LD C,07FH ;Load on mask STRIP8_OFF: LD (HL),C ;Patch AND instruction CHK_SHOW: LD A,(RESP_SHOW) ;Check if show given OR A JR Z,CHK_HELP ;Check for help AND 0A0H ;Is it boolean JP NZ,BAD_PARAM ;Error if not LD A,(SHOW_VAL) ;Get the value OR A ;Make sure not (SHOW=NO) CALL NZ,SHOW_VALS CHK_HELP: LD A,(RESP_HELP) ;Check if HELP given OR A JR Z,SET_EXIT AND 0A0H ;Is it boolean? JP NZ,BAD_PARAM LD A,(HELP_VAL) ;Get the value OR A ;Make sure not (HELP=NO) JP Z,SET_EXIT LD HL,HELP_STR SSVC @DSPLY SET_EXIT: LD HL,0 ;Set normal exit code RET ;Return, DON'T @EXIT HERE ; ; Show the values of the currently set options ; SHOW_VALS: LD HL,LINE_STR ;Get the line mode cursor descr SSVC @DSPLY ;Display it LD L,(IX+VE) ;Get the value LD H,0 ;Make it only a byte CALL NUMOUT ;Print it on the screen LD HL,BLK_STR ;Print the block mode descr SSVC @DSPLY LD L,(IX+VS) ;Get the value LD H,0 ;Make it a byte CALL NUMOUT ;Print the number on the display LD C,13 ;Get a new line SSVC @DSP LD HL,BELL_STR ;Print the BELL descr SSVC @DSPLY LD HL,ON_STR ;Get the ON string LD A,(IX+BELLFLAG) ;Get the value OR A ;Check if it is on JR NZ,SHOW_1 ;Jump if it is LD HL,OFF_STR ;Get the off string SHOW_1 SSVC @DSPLY ;Display ON or OFF LD HL,DURA_STR ;Get the duration descr SSVC @DSPLY LD L,(IX+DEF_LEN) ;Get the duration LD H,0 ;Make it a byte in HL CALL NUMOUT ;Print the number on the screen LD HL,FREQ_STR ;Print the frequency descr SSVC @DSPLY LD L,(IX+DEF_FREQ) ;Get the LSB of FREQ LD H,(IX+DEF_FREQ+1);Get the MSB CALL NUMOUT ;Print the number out LD HL,STRIP_STR ;Get the STRIP8 message SSVC @DSPLY LD C,(IX+BIT_MASK) LD B,(IX+BIT_MASK+1) PUSH IX POP HL ADD HL,BC ;Compute the offset LD A,(HL) LD HL,ONSTR CP 0FFH ;Check for off JR NZ,ISON LD HL,OFFSTR ISON: SSVC @DSPLY RET ;Return to caller ; NUMOUT LD DE,STRBUF PUSH DE SSVC @HEXDEC EX DE,HL LD (HL),3 POP HL LD A,' ' NUM_1 CP (HL) JR NZ,NUM_2 INC HL JR NUM_1 NUM_2 SSVC @DSPLY RET ; CANT_REMOVE: LD HL,NO_REMOVE ;Print the Can't remove message SSVC @DSPLY JP REMOVE_FILTER ;Finish unlinking the devices ; TOO_BIG: LD HL,TOO_BIG_STR ;Get the TOO BIG message DB 0DDH ;Hide LD HL instruction ; NOH19MESS: LD HL,NOFLT_STR ;Print error message, No H19/FLT DB 0DDH ;Hide LD HL ; BAD_PARAM LD HL,BAD_PARAM_STR;Print Bad paramter message ; PRINT_EXIT: SSVC @DSPLY ;Print it EXIT: LD HL,-1 ;Get error exit code RET ;Return from caller ; ERROR: OR 0C0H LD C,A SSVC @ERROR JR EXIT ; NOH19: LD A,(ONCE) ;Check if we have been here once OR A JR NZ,NOH19MESS ;If so, then issue a message INC A ;Set the flag LD (ONCE),A LD HL,SETH19 ;Do the "set *hp h19" command SSVC @CMNDR LD HL,FILTER ;Do the "filter *so *hp" command SSVC @CMNDR JP GETH19 ;Try to load it again ; H19_NAME DB '$HEATH',0 NO_REMOVE DB 'Can not reclaim used memory!',13 STRIP_STR DB 10,'Strip 8th bit: ',3 ONSTR DB 'YES',13 OFFSTR DB 'NO',13 NOFLT_STR DB 'Can not find H19 filter',13 BAD_PARAM_STR DB 'Bad parameter value',13 TOO_BIG_STR DB 'Value too large',13 LINE_STR DB 'Normal cursor: ',3 BLK_STR DB ', Block cursor: ',3 DURA_STR DB ', Duration: ',3 FREQ_STR DB ', Frequency: ',3 BELL_STR DB 'Bell: ',3 ON_STR DB 'ON',3 OFF_STR DB 'OFF',3 ; HELP_STR DB 'Recognized parameters:',10 DB 'CURSOR - Normal cursor character',10 DB 'BLOCK - Block cursor character',10 DB 'BELL - Turn bell ON or OFF',10 DB 'FREQUENCY - Frequency of bell (inverse of ' DB 'real freq)',10 DB 'DURATION - Length of tone (255 MAX)',10 DB 'STRIP8 - Remove 8th bit from characters ' DB '(default=ON)',10 DB 'REMOVE - Remove the filter from memory' DB 10,'SHOW - Show all values',10 DB 'HELP - This message',10,13 ; VE_VAL DW 0 VS_VAL DW 0 RM_FLAG DW 0 DUR_VAL DW 0 FREQ_VAL DW 0 BELL_VAL DW 0 SHOW_VAL DW 0 HELP_VAL DW 0 STRIP8_VAL DW 0 ; CMD1 DB 'reset *so',13 CMD2 DB 'reset *hp',13 CMD3 DB 'remove *hp',13 CMD4 DB 'route *so *do',13 SETH19 DB 'set *hp h19',13 FILTER DB 'filter *so *hp' PARMS DW 0 ONCE DB 0 ARGBUFF DB ' ' DS 255 STRBUF DS 20 ; PARAM_TABLE: DB 80H ; DB 80H+5 DB 'BLOCK' RESP_VS DB 0 DW VS_VAL ; DB 80H+6 DB 'CURSOR' RESP_VE DB 0 DW VE_VAL ; DB 40H+6 DB 'REMOVE' RESP_REMOVE DB 0 DW RM_FLAG ; DB 90H+9 DB 'FREQUENCY' RESP_FREQ DB 0 DW FREQ_VAL ; DB 90H+8 DB 'DURATION' RESP_DURA DB 0 DW DUR_VAL ; DB 40H+4 DB 'BELL' RESP_BELL DB 0 DW BELL_VAL ; DB 40H+4 DB 'SHOW' RESP_SHOW DB 0 DW SHOW_VAL ; DB 40H+4 DB 'HELP' RESP_HELP DB 0 DW HELP_VAL ; DB 46H DB 'STRIP8' RESP_STRIP8 DB 0 DW STRIP8_VAL ; TABLE_END DB 0 END START <<< m4key.asm >>> ; m4key/asm ; GETKEY EQU $ LD HL,(KEYPOS) ;Get the buffered keys address GETKEY_0 EQU $ LD A,(HL) ;Get the key there IFZ GETKEY_1 ;Jump if no key available INC HL ;Point to next LD (KEYPOS),HL ;Save the new pointer CP A ;Set Z status RET ;Return the key ; ; Here, we must change the current string pointer back to a KNOWN ; zero byte. Otherwise the next defintion may move non-zero data ; underneath the pointer and result in garbage being retrieved on ; the next call to GETKEY. ; GETKEY_1 EQU $ LD HL,ATNULL ;Replace current string pointer LD (KEYPOS),HL CALL TRMIN ;Get a key from *SI RET NZ ;Return if nothing there LD (SAVEDKEY),A ;Save it for later use CALL KEYTRANS ;Get the address from the table OR H ;A holds L, OR in H to check JR NZ,GETKEY_0 ;Jump if string is present LD A,(SAVEDKEY) ;Get the real key back CP A ;Set Z status RET ;Return the key ; ; Store a key definition into the table ; DEFKEY EQU $ LD (KEYSTRING),HL ;Save the pointer to the data LD (KEYNUMBER),A ;Save the key to be replaced PUSH AF LD A,B ;Get the number of bytes in (HL) LD (STRINGLEN),A ;Store it POP AF CALL KEYTRANS ;Get the address of the current OR H ;definition and see if one exists CALL NZ,DELETEKEY ;If so, then remove it LD A,(STRINGLEN) ;Get the length OR A ;Is there a string there? RET Z ;Return if none. Old was deleted LD HL,DEFTABLE+DEFTLEN-1;Get the top of the table LD DE,(TOPADDR) ;Get the start of available OR A ;Reset carry SBC HL,DE ;Compute available number bytes LD C,A ;Get the request size as 16 bits LD B,0 OR A ;Reset the carry SBC HL,BC ;Compute the remaining after use JR NC,DEFKEY_1 ;Jump if there is room for it LD DE,NOSPACE ;Print the error message CALL PRTSTR RET ;Return without defining it DEFKEY_1 EQU $ LD HL,(KEYSTRING) ;Get the new definition PUSH DE ;Save the address to store at LDIR ;Move the string EX DE,HL ;Get the ending address LD (HL),0 ;Put a NULL in INC HL ;Point to next available LD (TOPADDR),HL ;Save the new available address POP DE ;Restore the definition address LD HL,(TABLEADDR) ;Get the address in the table LD (HL),E ;Store the LSB INC HL ;Point to the MSB LD (HL),D ;Save the MSB RET ;Return to the caller ; ; Get the address of the string corresponding to the key number ; in A. A holds the value of H on return. HL is zero if no ; definition exists. HL is the address of the string that is ; defined for the key if it is non-zero. The last byte in the ; string is followed by a zero byte. ; KEYTRANS EQU $ LD HL,KEYTABLE ;Get the pointer table LD C,A ;Put it into C LD B,0 ;Set B to zero initially RLC C ;C = C * 2 JR NC,KEYTRANS_1 ;If carry on shift then c > 127, INC B ;so increment B to recover bit 7 KEYTRANS_1 EQU $ RES 0,C ;Reset the LSB of C. ADD HL,BC ;Compute the table address LD (TABLEADDR),HL ;Save the address of the key def LD A,(HL) ;Get the LSB INC HL ;Point to the MSB LD H,(HL) ;Get it LD L,A ;Get the LSB RET ;Return to caller ; ; Delete a key definition from the table. No parameters are ; needed. The key to undefine is pointed to by (TABLEADDR). ; Thus, you must call KEYTRANS with the key number in A and then ; call DELETEKEY to delete the key. ; DELETEKEY EQU $ LD HL,(TABLEADDR) ;Get the addr of the definition LD E,(HL) ;Get the LSB of the string XOR A ;Clear A LD (HL),A ;Zap the LSB INC HL ;Point to the MSB LD D,(HL) ;Get the MSB LD (HL),A ;Zap the MSB LD (CMPADDR),DE ;Save the address for compares LD H,D ;Copy DE to HL LD L,E ; XOR A ;A is already zero (what we seek) CPIR ;Look for it PUSH HL ;Save the ending address OR A ;Reset the carry SBC HL,DE ;Compute the difference LD (MOVEDIFF),HL ;Save the difference LD HL,(TOPADDR) ;Get the end of the table POP BC ;Get the end of string to delete OR A ;reset the carry SBC HL,BC ;Calculate number bytes to move PUSH BC ;Exchange HL and BC PUSH HL POP BC POP HL LD A,B ;Check for zero length OR C JR Z,DELETEKEY_1 ;Don't move 65536 bytes LDIR ;Adjust the strings down DELETEKEY_1 EQU $ LD (TOPADDR),DE ;Set the new top address LD HL,KEYTABLE ;Get start of table LD B,0 ;Check 256 entrys DELETEKEY_2 EQU $ PUSH BC ;Save the counter LD C,(HL) ;Get the table value LSB INC HL ;Point to MSB LD B,(HL) ;Get the MSB DEC HL ;Back to original address LD A,B ;Check for any definition OR C ;Set the flags JR Z,DELETEKEY_4 ;Skip this entry PUSH HL ;Save the table address LD HL,(CMPADDR) ;Get the address to check against OR A ;Reset the carry SBC HL,BC ;Compute the difference JP P,DELETEKEY_3 ;Jump if no adjust needed LD H,B ;Copy BC to HL LD L,C LD BC,(MOVEDIFF) ;Get the difference OR A ;Reset the carry SBC HL,BC ;Adjust the pointer LD C,L ;Copy HL to BC LD B,H ;Get the MSB POP HL ;Get the destination address LD (HL),C ;Store the LSB back INC HL ;Point to MSB LD (HL),B ;Store the MSB JR DELETEKEY_5 ;Join other code DELETEKEY_3 EQU $ POP HL ;Get the table address back DELETEKEY_4 EQU $ INC HL ;Point to next table pos DELETEKEY_5 EQU $ INC HL ;One more increment POP BC ;Get the counter back DJNZ DELETEKEY_2 ;Loop until done RET ;end of file <<< m4log.asm >>> ; M4LOG/ASM ; LOGON SCRIPT INTERPRETER ; ; OUTPUT STRING TO PORT ; ; This code performs the OUTPUT function. Control characters ; are ignored in the output string as far as matching is concerned, ; and they are also ignored in the input port. This allows more ; flexability as far as text recognition is concerned. ; ; e.g. The string XYZPDQ will be output exactly as ; specified, but only the characters "XYZPDQ" will be matched if ; SET OUTPUT HOST-ECHO is ON. Any control characters will be ; ignored. ; OUTPUT EQU $ LD A,CMTXT ;GET SOME TEXT TO SEND LD DE,DATA ;WHERE TO PUT THE STRING LD (SOUPTR),DE ;SET THE ORIGINAL DATA ADDRESS CALL COMND ;GET IT JP KERMT3 ;SAY NOT CONFIRMED ON ERROR LD A,1 LD (SNDFLG),A OUTPUT1 CALL GETFCH ;GET A CHARACTER JR NZ,OUTPUT5 CALL GTREAL ;GET THE ACTUAL IF IT IS SPECIAL JP NZ,SOU400 ;QUIT ON AN ERROR LD E,A ;PUT IT IN E FOR OUTCHR LD A,(DLYFLG) ;WAS IT A DELAY IFZ OUTPUT2 ;Jump is no delay XOR A LD (DLYFLG),A ;RESET THE FLAG JR OUTPUT1 ;GET A NEW CHARACTER OUTPUT2 CALL OUTCHR ;OUT THE PORT WITH IT LD A,(LOGFLG) ;DO WE NEED TO LOGIT TO THE FILE OR A LD A,E ;RESTORE THE CHARACTER IN A CALL NZ,LOGIT ;LOG IT IF LOGFLG IS SET IFALT 32,OUTPUT1 LD A,(ECHFLG) ;IS ECHO ON? IFZ OUTPUT1 ;If not than get the next to send LD A,E ;GET THE CHARACTER BACK IN A PUSH AF ;SAVE IT FOR A SEC OUTPUT3 CALL INPORT ;GET ONE CHARACTER FROM THE PORT JR Z,OUTPUT4 ;Got a character so check it CALL CONIN ;IS THERE A KEY PRESSED? IFZ OUTPUT3 ;Go if there isn't CP 128 ;IS IT BREAK JP Z,SBORT ;QUIT IF IT IS CP 27 ;IS IT ESCAPE JP Z,QUTOUT ;Skip this command CP 129 ;CHECK FOR F1 PRESSED JP Z,QUTOUT ;Skip this command JR OUTPUT3 ;TRY AGAIN TO GET THE ECHO OUTPUT4 LD E,A LD A,(OTDSP) ;LOCAL ECHO ON? OR A LD A,E ;RESTORE A FOR THE CALL TO TRMOUT CALL NZ,TRMOUT ;DISPLAY THE CHARACTER LD A,(LOGFLG) ;IS LOGGING SET? OR A LD A,E CALL NZ,LOGIT ;LOG WHAT WE RECEIVED CALL SETCSE ;SET THE CASE LD E,A ;PUT IT IN E POP AF ;GET THE CHARACTER WE SENT CALL SETCSE ;SET THE CASE IFA E,OUTPUT1 LD A,E IFALT 32,OUTPUT1 ;Ignore CNTL that doesn't match LD DE,NOECHO ;LOAD NO REMOTE-HOST ECHO ERROR JP SBORT2 ;QUIT, NO MATCH OUTPUT5 XOR A ;RESET STATE FLAG LD (SNDFLG),A JP KERMIT ;GET A NEW COMMAND ; ; Do receive character matching. ; ; The KMP pattern matching algorithm is used here for the fun of ; it. In reality, we probably don't need this much power, but ; it is rather elegant!!! ; INPUT EQU $ LD A,CMTXT ;GET SOMETHING TO SEND LD DE,DATA ;WHERE TO PUT THE TEXT LD (SOUPTR),DE ;SAVE THE ADDRESS FOR GETFCH CALL COMND ;GET SOME TEXT, OR FAIL JP KERMT3 ;SAY NOT CONFIRMED ON FAILURE LD A,1 LD (RECFLG),A LD HL,STRING ;GET ADDRESS OF THE BUFFER LD B,0 ;B IS THE LENGTH COUNTER ; ; Gather the string to receive ; INPUT1 CALL GETFCH ;GET A CHARACTER JP NZ,INPUT3 ;QUIT ON AN ERROR CALL GTREAL ;CONVERT ESCAPES, ETC... JP NZ,SOU400 ;QUIT ON AN ERROR LD E,A ;SAVE THE CHARACTER FOR A SEC LD A,(DLYFLG) ;WAS IT A DELAY? IFZ INPUT2 ;Jump if not XOR A ;CLEAR A LD (DLYFLG),A ;RESET THE FLAG JR INPUT1 INPUT2 LD (HL),E ;STORE WHAT WE GOT INC HL ;POINT TO THE NEXT INC B ;ONE MORE TO LENGTH JR NZ,INPUT1 ;JUMP IF NOT BUFFER OVERFLOW LD DE,STOBIG ;LOAD error MESSAGE STRING CALL PRTSTR ;PRINT IT ON THE SCREEN. JP SOU540 ;Jump to end INPUT3 LD (HL),0 ;END IT WITH A NULL ; ; KMP really begins here. The basic C code is in the comments! ; Build the failure link table... ; LD A,B ;B IS THE LENGTH LD (LENGTH),A ;SAVE THE LENGTH M=STRLEN(STR) XOR A ;ZERO a FOR FLINK[1]=0 LD C,1 ;SUBSCRIPT 1 CALL SETLNK ;FLINK[1]=0; LD D,2 ;I=2; INPUT4 LD C,D ;GET I LD A,(LENGTH) ;GET THE LENGTH OF THE STRING CP C ;IF (I <= M) { JP M,INPUT7 ;Jump if I > M LD C,D ;c = I DEC C ;c = I-1 CALL GETLNK ;a = FLINK[c] LD E,A ;J = FLINK[I-1] INPUT5 INC E ;IF (I != 0 DEC E JR Z,INPUT6 ;JUMP IF I = 0 LD C,E ;c = J CALL GETSTG ;a = STRING[J] LD B,A ;b = a LD C,D ;c = I DEC C ;c = I - 1 CALL GETSTG ;a = STRING[I-1] IFA B,INPUT6 LD C,E ;c = J CALL GETLNK ;a = FLINK[J] LD E,A ;J = FLINK[J] JR INPUT5 INPUT6 LD A,E ;A = J INC A ;A = J+1 LD C,D ;C = I CALL SETLNK ;FLINK[I] = J+1 INC D ;I++ JR INPUT4 INPUT7 LD E,0 ;J = 0 LD A,(HSTCHR) ;GET ANY LEFT OVER CHARACTERS IFZ INPUT12 LD C,A ;SAVE A FOR A SEC XOR A ;CLEAR IT OUT LD (HSTCHR),A ;SAY NO REMAINING HOST CHARACTER LD A,C ;RESTORE A INPUT8 LD (CHRGOT),A LD C,A ;SAVE THE CHARACTER LD A,(INDSP) ;CHECK IF WE SHOULD DISPLAY IFZ INPUT9 LD A,C ;GET THE CHARACTER BACK CALL TRMOUT ;PRINT IT INPUT9 LD A,(LOGFLG) ;IS LOGGING ON OR A ;SET THE FLAGS LD A,C ;RESTORE THE CHARACTER INTO A CALL NZ,LOGIT ;LOG THE CHARACTER TO THE FILE INC E ;++J INPUT10 INC E ;IS E == 0 DEC E JR Z,INPUT11 LD C,E ;C = J DEC C ;C = J-1 CALL GETSTG ;A = STRING[J-1] CALL SETCSE ;ADJUST THE CASE LD C,A ;C = A LD A,(CHRGOT) CALL SETCSE ;ADJUST THE CASE IFA C,INPUT11 LD C,E ;C = J CALL GETLNK ;A = FLINK[J] LD E,A ;J = FLINK[J] JR INPUT10 INPUT11 LD A,(LENGTH) ;ARE WE AT THE END IFA E,INPUT13 INPUT12 CALL INPORT ;GET A CHARACTER IF THERE JR Z,INPUT8 ;GO IF WE GOT ONE CALL CONIN ;IS THERE A KEY PRESSED IFZ INPUT12 CP 128 ;IS BREAK PRESSED JP Z,SBORT ;SBORT IF IT IS CP ESC ;IS IT ESCAPE JP Z,QUTOUT ;Skip this command CP 129 ;CHECK IF F1 IS PRESSED AS ESCAPE JP Z,QUTOUT ;Skip this command PUSH DE ;SAVE E LD E,A ;OUTCHR NEEDS CHAR IN E CALL OUTCHR ;SEND IT OUT THE PORT POP DE ;RESTORE E JR INPUT12 ;CHECK AGAIN INPUT13 XOR A ;RESET RECEIVE STATE FLAG LD (RECFLG),A JP KERMIT ;GET A NEW COMMAND ; ; DO MULTIPLE/REPEATING TRANSMITTION UNTIL A CHARACTER IS RECEIVED ; PULSE EQU $ LD A,CMTXT ;GET SOME TEXT LD DE,DATA ;WHERE TO PUT IT LD (SOUPTR),DE ;SAVE THE ADDRESS OF THE BUFFER CALL COMND ;GET SOME TEXT JP KERMT3 ;SAY NOT CONFIRMED ON FAILURE LD A,1 LD (MULFLG),A LD HL,MULBUF ;GET THE BUFFER LD (BUFPTR),HL ;SAVE THE START PULSE1 CALL GETFCH ;GET A CHARACTER JP NZ,PULSE3 ;QUIT ON AN ERROR CALL GTREAL ;GET THE ACTUAL CHARACTER JP NZ,SOU400 LD E,A LD A,(DLYFLG) ;WAS IT A DELAY? IFZ PULSE2 XOR A ;CLEAR A LD (DLYFLG),A ;RESET THE FLAG JR PULSE1 ;GET A NEW CHARACTER PULSE2 LD (HL),E ;SAVE THE CHARACTER INC HL ;POINT TO THE NEXT JR PULSE1 ;DO IT AGAIN PULSE3 PUTHL A ;Save the CR just found LD (HL),0 ;Terminate with a NULL PULSE4 LD BC,3000 ;DELAY COUNTER, MAGICAL NUMBER?!? PULSE5 CALL INPORT ;CHECK FOR A CHARACTER FIRST. JR Z,PULSE9 ;GO IF WE GOT ONE PUSH BC ;SAVE BC CALL CONIN ;CHECK THE KEYBOARD IFZ PULSE6 CP 128 ;IS IT BREAK? POP BC JP Z,SBORT ;SBORT IF IT IS CP ESC ;IS IT ESCAPE? JP Z,QUTOUT ;Skip this command CP 129 ;IS F1 PRESSED FOR ESCAPE? JP Z,QUTOUT ;Skip this command PUSH BC LD E,A ;PUT CHAR IN E FOR OUTCHR CALL OUTCHR ;OUTPUT THE SUCKER! LD A,(LOGFLG) ;CHECK FOR LOGGING TO FILE OR A LD A,E ;GET THE CHARACTER BACK CALL NZ,LOGIT ;GO LOG IT TO THE FILE IF FLAG PULSE6 POP BC DEC BC ;DECREMENT OUR COUNTER LD A,B ;CHECK IT FOR ZERO OR C JR NZ,PULSE5 ;LOOP UNTIL IT IS LD HL,MULBUF ;GET THE STRING ADDRESS PULSE7 LD A,(HL) ;GET A CHARACTER TO SEND CP CR ;IS IT THE END OF THE STRING? JR NZ,PULSE8 ;If not CR than jump INC HL ;CHECK FOR NULL TERMINATOR LD A,(HL) ;GET THE CHARACTER AFTER CR DEC HL ;POINT BACK ONE FOR FAIL IFZ PULSE4 PULSE8 INC HL ;POINT TO NEXT CHAR PUSH HL ;SAVE THE ADDRESS LD E,A ;SEND IT TO THE PORT CALL OUTCHR LD A,(LOGFLG) ;CHECK FOR LOGGING OR A LD A,E ;GET THE CHARACTER BACK CALL NZ,LOGIT ;GO LOG IT TO THE FILE POP HL ;GET THE ADDRESS BACK JR PULSE7 ;TO OF THE LOOP PULSE9 LD (HSTCHR),A ;SAVE THE SENT CHARACTER XOR A ;RESET THE STATE FLAG LD (MULFLG),A JP KERMIT ;GET A NEW COMMAND ; ; PAUSE FOR A CERTAIN NUMBER OF SECONDS ; PAUSE EQU $ LD A,CMNUM ;GET A WHILE TO PAUSE CALL COMND ;GET A NUMBER JP KERMT3 ;SAY NOT CONFIRMED ON AN ERROR IFNZ PAUSE1 ;Jump if at least one digit given LD DE,1 ;Use one second for the default PAUSE1 LD L,E ;SAVE IT LD H,D ;HL IN THE COUNT LD C,30 ;Count * 30 * HL = seconds delay CALL XMUL16 ;Multiply 16 bit HL by 8 bit C LD H,L ;Put the lower 16 bit of the 24 LD L,A ;bit result into HL LD (TIMER),HL ;STORE THE NUMBER LD C,8 ;TASK SLOT # 8 PAUSE2 CALL XCKTSK ;Is the task available? JR NZ,PAUSE3 LD IY,(FLAGS) ;Reset the special key bits in kflag$ LD A,(IY+10) ;Get it AND 0F8H ;Throw out , , and LD (IY+10),A ;Put it back LD DE,ALRMAD ;ADDRESS OF THE ALARM CALL XADTSK ;Add the task JR PAUSE5 ;Go wait for completion PAUSE3 INC C ;Get the next slot CP 11 JR NZ,PAUSE2 STROUT NODELAY ;Issue errormessage LD BC,0FFFFH ;Get a big value CALL XPAUSE ;Use @PAUSE to sleep for awhile JP KERMIT PAUSE5 LD HL,(TIMER) ;CHECK FOR ZERO YET LD A,H OR L JR NZ,PAUSE5 ;LOOP UNTIL EXPIRES JP KERMIT ;QUIT WHEN FLAG IS ZERO ; ; Set or ignore case based on "CSEFLG" ; SETCSE PUSH AF ;SAVE THE CHARACTER LD A,(CSEFLG) ;IS THE OPTION ON? IFZ CPS10 POP AF ;GET THE CHARACTER BACK CPTAL CP 'a' ;CHECK FOR LOWER CASE RET M CP 'z'+1 RET P AND 5FH ;MAKE IT UPPER IF IT IS LOWER JR CAPS20 CPS10 POP AF ;RESTORE AF CAPS20 RET ;RETURN TO THE CALLER ; ; INDEX STRING BY "C" ELEMENTS, AND PUT THE VALUE THERE IN A ; GETSTG LD HL,STRING ;GET STRING AS THE BASE JR GET100 ;JOIN THE CODE GETLNK LD HL,FLINK ;GET FLINK AS THE BASE GET100 PUSH BC ;SAVE BC FOR THE ADD LD B,0 ;MAKE BC A BYTE COUNT ADD HL,BC ;HL NOW POINTS TO IT LD A,(HL) ;A = HL[c] POP BC ;RESTORE BC RET ; ; ASSIGN THE C'th ELEMENT OF A STRING THE VALUE IN A ; SETSTG LD HL,STRING ;GET STRING AS THE BASE JR SET100 ;JOIN THE CODE SETLNK LD HL,FLINK ;GET FLINK AS THE BASE SET100 PUSH BC ;SAVE BC FOR THE ADD LD B,0 ;MAKE BC A BYTE OFFSET ADD HL,BC ;HL POINT TO IT NOW LD (HL),A ;HL[c] = A POP BC ;RESTORE BC RET ; ; PRINT THE MESSAGE IN DE AND QUIT WITH AN ERROR ; SBORT2 CALL PRTSTR ;DISPLAY THE MESSAGE JR SBORT ;CLOSE THE FILE AND EXIT ; ; ISSUE A SYSTEM ERROR MESSAGE FIRST AND SBORT ; SBORT1 CALL XERROR0 ;PRINT A SYSTEM MESSAGE SBORT STROUT LGFAIL ;Operation aborted message JP SOU540 ; ; SURRENDER THE TERMINAL TO THE USER ; QUTOUT STROUT QUTMES ;TELL THEM WHAT WE ARE DOING LD HL,(CMCPTR) LD (HL),EOS STROUT CMDBUF JP KERMIT ;GET A NEW COMMAND ; ; CONTROL COMES HERE AT EOF ; SOU400 LD A,(ESFLG) ;DID WE DIE IN AN ESC SEQ IFZ SOU420 STROUT PREESC ;Print the message JR SOU540 ;CHECK STATE FLAGS SOU420 LD A,(CTLFLG) ;DID WE DIE IN A CTL SEQ IFZ SOU430 STROUT PRECTL ;Print the message JR SOU540 ;CHECK STATE FLAGS SOU430 LD A,(OPTFLG) ;CHECK FOR TYPE EOF OR A JP Z,KERMIT ;ON THIS ONE, GOTO KERMIT STROUT PREOPT ;Print the message JR SOU540 SOU540 LD A,(EXTFLG) ;CHECK FOR EXIT AT EOF OR A ;IS IT SET JP Z,KERMIT ;GOTO GET MORE COMMANDS IF NOT LD A,(TAKFLG) ;CHECK IF TAKE ACTIVE OR A JP Z,KERMIT ;GOTO KERMIT IF NOT LD DE,TFCB CALL XCLOSE ;CLOSE THE TAKE FILE XOR A ;TURN TAKE OFF LD (TAKFLG),A JP KERMIT ;GET A NEW COMMAND ; ; GET \ ESCAPED OR CONTROL'D CHARACTER IF CONTENTS OF "A" SAY SO. ; ALSO , , , ARE RECOGNIZED HERE FOR SEND AND RECEIVE. ; HL MUST CONTAIN ADDRESS OF ROUTINE TO CALL FOR NEXT CHARACTER. ; RETURNS NZ STATUS IF SECOND GET FAILED, OTHERWIZE RETURNS Z. ; GTREAL PUSH HL ;SAVE THE REGS! PUSH BC PUSH DE IFANOT '\',GT010 XOR A LD B,A INC A LD (ESFLG),A CALL GETFCH ;CALL THE SPECIAL ROUTINE JP NZ,GT060 ;QUIT IF END IS FOUND CP '0' JP M,GT005 CP '9'+1 JP P,GT005 GT002 CP '0' JP M,GT003 CP '9'+1 JP P,GT003 SUB '0' SLA B SLA B SLA B ADD A,B LD B,A CALL GETFCH ;CALL THE SPECIAL ROUTINE JR Z,GT002 ;Go on success GT003 LD HL,(SOUPTR) ;Unput the character DEC HL LD (SOUPTR),HL LD (HL),A GT004 LD A,B GT005 PUSH AF XOR A LD (ESFLG),A POP AF JP GT050 GT010 IFANOT '^',GT020 ;Jump if not a control sequence LD A,1 ;SET THE FLAG FOR A GET ERROR LD (CTLFLG),A CALL GETFCH ;CALL THE SPECIAL ROUTINE JP NZ,GT060 SUB 40H ;CONTROLIFY IT BY SUBTRACTING "@" PUSH AF XOR A LD (CTLFLG),A POP AF JP GT050 GT020 CP '<' ;Is it an ANSI sequence JP NZ,GT050 ;RETURN Z STATUS IF NOT LD A,1 ;SET THE STATE FLAG LD (OPTFLG),A LD HL,GTSTRG ;WHERE TO STORE THE STRING GT023 CALL GETFCH ;GET A CHARACTER JP NZ,GT060 ;QUIT ON AN ERROR IFA '>',GT026 CALL CPTAL ;MAKE IT A CAPITAL PUTHL A ;Save the character JR GT023 ;GET SOME MORE GT026 LD (HL),0FFH ;IMPOSSIBLE CHARACTER AS EOL LD HL,CTLTBL ;TOP OF THE TABLE LD B,(HL) ;GET THE NUMBER OF ENTRIES INC HL ;POINT AT THE FIRST CHAR GT028 LD DE,GTSTRG ;Get the buffer we stored into GT030 LD A,(DE) ;Get a character IFANOT (HL),GT040 ;Does it match GT035 GETHL A ;Get the next character INC DE ;Point to next IFALT '0',GT037 ;Check valid range of characters IFAGE 'Z'+1,GT037 ;Jump if we are at the end marker JR GT030 ;Go get the rest of the string GT037 LD C,A ;Save the character LD A,(DE) ;Get the next IFANOT 0FFH,GT040 ;Error if not terminator LD A,C ;RESTORE THE CHARACTER CP DLY ;Is it a delay string? JP Z,DELAY ;Go do it if it is PUSH AF XOR A ;Reset the state flag for EOF LD (OPTFLG),A POP AF JP GT050 ;RETURN Z STATUS GT040 LD C,A ;SAVE THE CHARACTER LD A,(HL) ;WILD CARD? IFANOT '*',GT042 ;Jump if not wild LD A,C ;Get the delay character LD (WLDBUF),A ;SAVE IT IN THE BUFFER JR GT035 ;Join the code for end check GT042 LD A,0FEH ;WHAT TO LOOK FOR PUSH BC ;DON'T KILL B LD BC,0 ;Set max count CPIR ;LOOK AHEAD FOR THE NEXT POP BC ;RESTORE B DJNZ GT028 ;GO LOOK SOMEMORE JP NOCODE ;PRINT A MESSAGE DELAY LD A,(WLDBUF) ;GET THE CHARACTER SUB 48 ;MAKE IT BINARY LD L,A ;SAVE IT LD H,0 ;HL IN THE COUNT LD C,30 ;33.33 MILLISECS * 30 * HL = SECS CALL XMUL16 LD H,L ;SHIFT IT ALL INTO HL LD L,A ;HL = HL * 120 LD (TIMER),HL LD IY,(FLAGS) ;Reset the special key bits in kflag$ LD A,(IY+10) AND 0F8H LD (IY+10),A LD C,8 ;TASK SLOT # 8 LD DE,ALRMAD ;ADDRESS OF THE ALARM CALL XADTSK GT034 LD HL,(TIMER) ;CHECK FOR ZERO YET LD A,H OR L JR NZ,GT034 ;LOOP UNTIL EXPIRES LD A,1 LD (DLYFLG),A ;SET THE DELAY FLAG GT050 CP A ;SET Z STATUS GT060 POP DE ;RESTORE REGS POP BC POP HL RET ;RETURN TO THE CALLER ; ; Print an error message about a bad string inside <...>'s ; NOCODE STROUT BADCD ;PRINT A MESSAGE XOR A INC A ;SET NZ STATUS JR GT060 ; ; ALARM COUNTER ; ALARM PUSH HL ;Save the registers PUSH AF PUSH IY LD IY,(FLAGS) ;Get the system flags LD HL,(TIMER) ;PREVIOUS TIMER VALUE DEC HL ;DECREMENT IT LD (TIMER),HL ;SAVE THE NEW VALUE LD A,H ;IS IT ZERO YET OR L JR NZ,ALARM2 ALARM1 EQU $ RES 0,(IY+10) ;Reset the break bit POP IY POP AF POP HL CALL XKLTSK ;Remove the alarm task, doesn't return RET ;Just in case ALARM2 EQU $ BIT 0,(IY+10) ;Check the break bit JR Z,ALARM5 LD HL,0 LD (TIMER),HL LD H,50 ALARM3 DEC HL LD A,H OR L JR NZ,ALARM3 JR ALARM1 ALARM5 EQU $ POP IY POP AF POP HL RET ; ; GET THE NEXT CHARACTER FROM THE BUFFER ; GETFCH PUSH HL LD HL,(SOUPTR) LD A,(HL) INC HL LD (SOUPTR),HL IFA CR,GTF010 CP A POP HL RET GTF010 CP CR+1 ;Force NZ to be set POP HL RET END ;end of file <<< m4mac.asm >>> ; m4mac/asm *LIST OFF PUTHL MACRO #P1 LD (HL),#P1 INC HL ENDM ; ; Protocol switch macro ; ; Expansion is something like: ; ; CP 'D' ; JR NZ,SWAA ; CALL SDATA ; JP PROTO ;SWAA ; SWITCH MACRO #P1,#P2 CP #P1 JR NZ,SW? CALL #P2 JP PROTO SW? ENDM ; TOCHAR MACRO ADD A,32 ENDM ; STROUT MACRO #P1 LD DE,#P1 CALL PRTSTR ENDM ; SPACKET MACRO #P1 LD A,#P1 CALL SPACK JP ABORT ENDM ; RPACKET MACRO CALL RPACK JP QUIT ENDM ; NSTATE MACRO #P1 LD A,#P1 LD (STATE),A ENDM ; IFANOT MACRO #P1,#P2 CP #P1 JR NZ,#P2 ENDM ; IFALT MACRO #P1,#P2 CP #P1 JR C,#P2 ENDM ; IFAGE MACRO #P1,#P2 CP #P1 JR NC,#P2 ENDM ; IFA MACRO #P1,#P2 CP #P1 JR Z,#P2 ENDM ; IFZ MACRO #P1 OR A JR Z,#P1 ENDM ; GENCASE MACRO #P1,#P2 LD A,#P2 LD (FLDLEN),A LD A,#P1 JP GENCMD ENDM ; GETHL MACRO #P1 INC HL LD #P1,(HL) ENDM ; ADDPUT MACRO #P1 LD A,(#P1) CALL TCHPUT ENDM ; SRPACK MACRO #P1 LD A,#P1 CALL SPACK JP ABORT RPACKET ENDM ; GETCRCTAB MACRO LD C,A LD HL,CRCTAB ADD HL,BC ADD HL,BC ENDM ; XORATHL MACRO #P1 LD A,#P1 XOR (HL) LD #P1,A ENDM ; CHKWKEY MACRO #P1 IFA #P1,INCHR5 ENDM ; IFNZ MACRO #P1 OR A JR NZ,#P1 ENDM ; SETFLG MACRO #P1 CALL ONOFF LD (#P1),A JP KERMIT ENDM ; SHOFFON MACRO #P1 LD A,(#P1) CALL COFFON JP NEWLIN ENDM ; FOFFON MACRO #P1 LD A,(#P1) CALL COFFON CALL NEWLIN ENDM ; SHRSTAT MACRO #P1,#P2 FORMAT #P1,SRSTRLEN LD A,(#P2) CALL ANOUT CALL NEWLIN ENDM ; SHSSTAT MACRO #P1,#P2 FORMAT #P1,SRSTRLEN LD A,(#P2) CALL ANOUT CALL NEWLIN ENDM ; DOSVC MACRO #P1 LD A,#P1 RST 28H LD (XERRNO),A RET ENDM ; FORMAT MACRO #P1,#P2 LD HL,#P2 LD DE,#P1 CALL LEFTPAD ENDM ; TRLOG MACRO #P1,#P2 LD HL,#P1 CALL OUTLOG JP #P2 ENDM *LIST ON <<< m4mit.asm >>> ; M4MIT/ASM ; ORG 6000H ; ; Model 4(p) KERMIT by Gregg Wonderly ; ; Version 5.2 ; ; Version 5.2 adds wild card send capabilities as well as fixes ; to bugs. M4CHGS/ASM contains a list of the changes made between ; version 5.0, and 5.2. ; ; This version is a radically modified and rewritten version ; of the original TRS-80 KERMIT done by Stan Barber. It has ; numerous features and capabilities beyond that version due ; to differences between the Model 3 and 4. ; ; Get the macro definitions first ; *GET M4EQU *GET M4MAC ; ; Entry point for execution ; START LD (OLDSP),SP ;Save the current stack pointer for later LD SP,STACK ;Set up the stack to our area CALL XFLAGS ;Get the flags address in IY LD (FLAGS),IY ;Save the flags for later LD HL,SWTBUF ;Clear initial connect screen buffer LD DE,SWTBUF+1 LD BC,1920 ;Byte counter LD (HL),' ' ;Clear the first character LDIR ;Copy it to the next LD B,1 ;Move low memory up above our code. LD HL,0 ;Select GET option of @HIGH$ CALL XHIGH ;Get the current LOW$ JP NZ,BADMEM ;Quit on an error LD (OLDLOW),HL ;Save for restore on exit LD HL,TOPMEM ;Get the last address used CALL XHIGH ;Store it as the new LOW$ JP NZ,BADMEM ;Quit on an error LD E,'C' ;Look for the *CL DCB LD D,'L' CALL XGTDCB ;The address comes back in HL LD (CLDCB),HL ;Save the address (May be wrong) JR NZ,NOCL ;Now check for error... LD E,'S' ;Look for the *SI DCB LD D,'I' CALL XGTDCB ;The address comes back in HL LD (TMIDCB),HL ;Store the result JR NZ,NOSI ;Skip if NOT found or other error LD E,'S' ;Look for the *SO DCB LD D,'O' CALL XGTDCB ;The address comes back in HL LD (TMODCB),HL ;Save the address JR NZ,NOSO ;Jump if NOT found or other error CALL SETINT ;Set up interupt receiver etc XOR A ;ZERO A LD (FCB),A ;SET FILE CLOSED FLAG CALL CMBLNK ;CLEAR THE SCREEN STROUT INTRO ;Print the intro message CALL CHKTAK ;Check if there is a KERMIT/INI file CALL KERMIT ;Start accepting commands. JP EXIT1 ;If control returns, then exit ; ; Error messages printed when devices can not be found or allocated ; NOCL LD DE,CFCL ;Error message (Can't find *CL DCB) PRTOOPS CALL PRTSTR ;Print an OOPS message, and quit JP EXIT2 ;Finish cleaning up ; ; No DCB for the SI device was found ; NOSI LD DE,CFSI ;Get the message JR PRTOOPS ;Go print it ; ; No DCB for the SO device was found ; NOSO LD DE,CFSO ;Get the message JR PRTOOPS ;Go print it ; ; Bad return code from @HIGH$ call ; BADMEM CALL XERROR0 ;Print a system error message STROUT NOMEM ;Print the message JP XEXIT ;Exit to TRSDOS ; ; CLEAR THE SCREEN, SAVING DE ; CMBLNK PUSH DE ;Save DE STROUT CLRTOP ;Clear the screen POP DE ;Restore DE QUIT RET ;Just a simple return for QUIT ; ; KERMIT command processor ; This is where each command originates. ; KERMIT LD SP,STACK ;Set the stack back LD DE,FCB ;Always close an open file LD A,(DE) ;Get the flags byte BIT 7,A ;Is the file still open? CALL NZ,XCLOSE ;Close it if it is LD DE,KERM ;Get the prompt CALL PROMPT ;Display it, and set up the parser LD DE,COMTAB ;Get the primary command table LD A,CMKEY ;Parse a keyword CALL COMND ;Get a command or ERROR JP KERMT2 ;Abort on ERROR LD HL,KERMIT ;Put on a return address for the PUSH HL ;FINISH, LOGOUT, and BYE commands. PUSH HL LD HL,KERMTB ;Get the JUMP table for these commands LD C,A ;Make BC = A extended to 16 bits LD B,0 ;high byte is zero, (unsigned) ADD HL,BC ;Calculate the effective address JP (HL) ;Jump into the jump table ; ; Jump table for primary commands ; KERMTB JP REMOTE ;REMOTE JP EXIT ;EXIT JP CONNECT ;CONNECT JP LOG ;LOG JP READ ;RECEIVE JP SEND ;SEND JP SETCOM ;SET JP SHOW ;SHOW JP STATUS ;STATUS JP FINISH ;FINISH JP LOGOUT ;LOGOUT JP BYE ;BYE JP DIR ;DIRECTORY JP ERA ;KILL JP LOCCOM ;LOCAL JP SETCL ;SETCOM JP TAKE ;TAKE JP INPUT ;INPUT JP OUTPUT ;OUTPUT JP PAUSE ;PAUSE JP PULSE ;PULSE JP CLEARC ;CLEAR JP CLSFLS ;CLOSE JP ECHO ;Type text to screen ; ; Echo text to screen ; ECHO EQU $ LD A,CMTXT ;Get some text LD DE,DATA ;Where to put it PUSH DE ;Save for printing CALL COMND ;Parse it JP KERMT3 ;Jump on error POP HL ;Get the start LD C,A ;Make BC the length that is in A LD B,0 ADD HL,BC ;Move to EOS position LD (HL),EOS ;Put it in place CALL NEWLIN ;Get a new line STROUT DATA ;Print the string JP KERMIT ;Get a new command ; ; CLEAR command. Services CLEAR INPUT-PORT, and CLEAR SCREEN ; CLEARC LD A,CMKEY ;GET A KEYWORD LD DE,CLRTAB ;FROM THIS TABLE CALL COMND JP KERMT2 ;SAY UNRECOGNIZED COMMAND ON AN ERROR LD (TEMP1),A ;SAVE THE RETURNED VALUE LD A,CMCFM CALL COMND JP KERMT3 LD A,(TEMP1) LD C,A IFNZ CLR010 CALL CLRPRT ;DO "CLEAR INPUT-PORT" JP KERMIT ;GET A NEW COMMAND CLR010 CP 3 ;IS IT CLEAR SCREEN? JP NZ,KERMT2 ;SAY UNRECOGNIZED COMMAND IT NOT CALL CMBLNK ;CLEAR THE SCREEN JP KERMIT ;GET A NEW COMMAND ; ; TAKE commands from a file. This is basically a HACK that ; initializes some values so that GETSTR reads from the file, ; instead of the keyboard, until EOF is found. ; TAKE LD DE,TFCB ;WHERE TO PUT THE FILENAME LD A,CMIFI ;GET A FILE NAME CALL COMND ;GET USER INPUT JP KERMT3 ;ABORT ON AN ERROR OR A JP Z,KERMT3 ;Abort if no name given LD IY,(FLAGS) ;GET THE SYSTEM FLAGS SET 0,(IY+18) ;SET UP FOR NO FILE OPEN BIT LD HL,TBUF ;THIS IS THE DATA BUFFER LD DE,TFCB ;GET THE FILE FCB LD B,0 ;256 BYTE LRL CALL XOPEN ;TRY TO OPEN THE FILE JR NZ,TERROR ;GO REPORT AN ERROR LD A,1 LD (TAKFLG),A ;SET THE FLAG JP KERMIT TERROR CALL XERROR0 ;PRINT THE MESSAGE XOR A ;RESET THE TAKE FLAG LD (TAKFLG),A JP KERMIT ;GET A NEW COMMAND ; ; SETCOM command. We use the TRSDOS SETCOM command here, as it ; saves lots of time and trouble. ; SETCL LD A,CMTXT ;GET ARBITRARY TEXT LD DE,CLBUF ;BUFFER TO PUT DATA INTO CALL COMND ;GET THE INPUT JP KERMT3 ;ABORT ON ERROR CALL NEWLIN ;NEED A NEW LINE TO PRINT ON LD A,CR ;Get the EOL character LD (DE),A ;Put in the terminator LD HL,CLBUF-7 ;Get the 'SETCOM ' prefix CALL XCMNDR ;Let TRSDOS do it for us JP KERMIT ;Get a new command, ignoring any errors ; ; LOCAL command. Use @CMNDR to execute a TRSDOS command ; LOCCOM LD HL,(CMDPTR) ;GET THE ADDRESS OF THE START SYST1 LD A,(HL) ;GET A CHARACTER INC HL ;POINT TO THE NEXT IFA ' ',SYST1 ;Loop if just a blank IFA CR,SYST2 ;Do a LIB command if no text given IFANOT '?',SYST4 ;Go if user not asking for HELP SYST2 PUSH HL ;SAVE THE ADDRESS TO PASS POP IY ;GET A THE ADDRESS IN AN INDEX LD (IY-1),'L' ;HL GO INCREMENTED UP THERE LD (IY),'I' ;SPELLING OUT LIB LD (IY+1),'B' LD (IY+2),CR ;ADD THE TERMINATOR SYST4 DEC HL ;POINT TO THE ACTUAL ADDRESS CALL NEWLIN ;NEED A NEW LINE ; ; Remove the comments below to force LOCAL to process only library ; commands ; ; LD IY,(FLAGS) ;Get the Flags pointer ; SET 4,(IY+2) ;Only library commands are allowed CALL XCMNDR ;Do a system command SYST5 JP KERMIT ;IGNORE ANY ERRORS ; ; Print UNRECOGNIZED COMMAND message ; KERMT2 STROUT ERMES1 ;Issue the message JP KERMIT ; ; Print NOT CONFIRMED message ; KERMT3 STROUT ERMES3 ;Issue the message JP KERMIT ; ; Exit to TRSDOS ; EXIT LD A,CMCFM ;Get a confirmation of the EXIT CALL COMND JP KERMT3 EXIT1 LD DE,FCB ;Check the file FCB, and close if needed LD A,(DE) ;Get the info byte BIT 7,A ;Check the file open BIT CALL NZ,XCLOSE ;Close it if needed ; ; Check the log files to make sure they are closed ; LD DE,LFCB ;Get the file FCB LD A,(LOGFLG) ;Check if logging active OR A ;Check the flags CALL NZ,XCLOSE ;Close the file if open LD DE,DFCB ;Check debugging LD A,(DEBLOG) ;Get the flag OR A CALL NZ,XCLOSE ;Close it if open LD DE,TFCB ;Get the FCB LD A,(TRANLOG) ;Get the flag OR A CALL NZ,XCLOSE ;Close it if open ; ; Now reset the interrupt vector for *CL. ; LD C,4 ;Interrupts option of the @CTL SVC LD IY,0 ;Reset the INTERRUPT vector of *CL LD DE,(CLDCB) ;Get the *CL DCB address CALL XCTL ;Use @CTL to do it CALL CMBLNK ;Clear the screen EXIT2 LD HL,(OLDLOW) ;Get the old low memory pointer LD B,1 ;Set B to indicate LOW$ CALL XHIGH ;Move the value back ; ; Now fill the *FO, and *FI devices DCB's with zeros. This ; will make the devices no longer available. ; LD HL,(FINDCB) ;Get the *FI DCB address CALL ZERO8 ;Fill it with zeroes LD HL,(FOTDCB) ;Do the same for *FO CALL ZERO8 ;Fill DCB with zeroes CALL STOPTIMER ;Stop the timer if still running LD SP,(OLDSP) ;Restore the old STACK pointer LD HL,0 ;Set OK exit LD IY,(FLAGS) ;If JCL active, then just return BIT 5,(IY+18) ;Check the BIT RET NZ ;Return if BIT is set JP XEXIT ;Exit via @EXIT ; ; Zero 8 bytes pointed to by HL ; ZERO8 LD B,8 ;Get the byte count ZERO8_1 LD (HL),0 ;Zap one byte INC HL ;Point to next DJNZ ZERO8_1 ;Loop until done RET ; ; CALL ERROR Prints the DATA area on a new line, and sets ; the state to ABORT. ; CALL ERROR1 Prints the DATA area on a new line. ; CALL ERROR2 Prints the DATA area on the same line ; CALL ERROR3 Prints the string pointed to by DE on a new line ; CALL ERRORD Prints a system error message corresponding to ; A, providing A is none zero. ; ERROR NSTATE 'A' ;Set the state to abort ; ERROR1 CALL NEWLIN ;Get a new line ; ERROR2 LD A,(ARGBLK+1) ;Get the length of the data LD C,A ;Put the length into BC LD B,0 LD HL,DATA ;Get the start of the DATA area PUSH HL ;Save it LD A,EOS ;Add EOS for printing CALL PUTTRN POP DE ;Get start back JP PRTSTR ;Print the string, and return ; ERROR3 PUSH DE ;Save the message CALL NEWLIN ;Get a new line POP DE ;Restore the message JP PRTSTR ;Print error message ; ERRORD OR A ;Display system error message RET Z ;IFF an error has occured JP XERROR0 ;Do system error ; ; Print the string in DE, followed by a new line ; FINMES CALL PRTSTR ;Print the message JP NEWLIN ;Get a newline and return ; ; The FINISH, BYE, and LOGOUT commands all need a return address ; on the stack. This is because the CHKTRYS routine will use it ; to abort the packet operations when MAXTRY retries are reached. ; ; This is the FINISH command. ; FINISH LD A,CMCFM CALL COMND ;GET A CONFIRM. JP KERMT3 CALL NEWLIN CALL CLRPRT ;CLEAR ANY STACKED NAKS XOR A ;DIDN'T GET A CONFIRM. LD (NUMTRY),A ;INITITIALIZE COUNT. LD A,'1' ;Set block check to single char LD (CURCHK),A ;. . . FINSH1 CALL CHKTRYS ;Check the retry threshold XOR A LD (ARGBLK),A ;MAKE IT PACKET NUMBER ZERO. LD A,1 LD (ARGBLK+1),A ;ONE PIECE OF DATA. LD HL,DATA LD (HL),'F' ;FINISH RUNNING KERMIT. LD A,'G' ;GENERIC COMMAND PACKET. CALL SPACK ;Send the packet JP FINSH1 ;On fail, try again CALL RPACK ;GET AN ACKNOWLEDGEMENT. JP FINSH1 ;On fail, try again CP 'Y' ;ACK? JP Z,KERMIT ;YES, WE ARE DONE. IFANOT 'E',FINSH2 ;Jump if not error packet CALL ERROR1 ;PRINT THE ERROR MESSAGE. JP KERMIT FINSH2 CP 'N' ;Is this a NAK? CALL NZ,CONOUT ;Output the packet type to term JR FINSH1 ;Resend the packet ; ; This is the LOGOUT command. ; LOGOUT LD A,CMCFM CALL COMND ;GET A CONFIRM. JP KERMT3 CALL NEWLIN CALL LOGO ;SEND THE LOGOUT PACKET. JP LOG111 ;GO GET ANOTHER COMMAND JP KERMIT ;WHETHER WE SUCCEED OR NOT. LOGO XOR A LD (NUMTRY),A ;INITITIALIZE COUNT. CALL CLRPRT ;CLEAR ANY STACKED NAKS LD A,'1' ;Block check type to single LD (CURCHK),A ;. . . LOGO1 CALL CHKTRYS ;Check retry threshold XOR A LD (ARGBLK),A ;MAKE IT PACKET NUMBER ZERO. LD A,1 LD (ARGBLK+1),A ;ONE PIECE OF DATA. LD HL,DATA LD (HL),'L' ;LOGOUT THE REMOTE HOST. LD A,'G' ;GENERIC COMMAND PACKET. CALL SPACK JP LOGO3 CALL RPACK ;GET AN ACKNOWLEDGEMENT JP LOGO1 CP 'Y' ;ACK? JP Z,RSKP ;YES, WE ARE DONE. CP 'E' ;IS IT AN ERROR PACKET? JP Z,ERROR1 ;Print the error message LOGO2 CP 'N' CALL NZ,CONOUT JR LOGO1 ; LOGO3 LD DE,ERMS19 ;Get the message JP PRTSTR ;Print it ; ; This is the BYE command ; BYE EQU $ LD A,CMCFM CALL COMND ;GET A CONFIRM. JP KERMT3 CALL NEWLIN CALL LOGO ;TELL THE MAIN FRAME TO LOGOUT. JP LOG111 ;IF IT FAILS, DON'T EXIT. JP EXIT1 ;EXIT KERMIT. LOG111 CALL NEWLIN ;GET A NEW LINE JP KERMIT ; ; Get the rest of the modules ; *GET M4FILE/ASM ;Log file code *GET M4CMD/ASM ;Command parser *GET M4SET/ASM ;Set command processing *GET M4TERM/ASM ;Terminal emulation *GET M4SHOW/ASM ;Show command processing *GET M4PKT/ASM ;Additional packet stuff *GET M4GET/ASM ;Receive protocol *GET M4SEND/ASM ;Send protocol *GET M4XFER/ASM ;Protocol common code *GET M4ADD/ASM ;TRSDOS SVC's and other system dependent stuff *GET M4RMT/ASM ;Remote commands *GET M4KEY/ASM ;Set key code *GET M4LOG/ASM ;Input, Output, Pause, Pulse commands *GET M4WILD/ASM ;Wild carding *GET M4STR/ASM ;Strings and storage TOPMEM EQU $+10 ;A little padding END START ;end of file <<< m4pkt.asm >>> ; m4pkt/asm ; ; Most of the code in this file was derived directly from ; the C-KERMIT program. The code here represents a line by ; line translation of the C-KERMIT code. ; MEMSTR DW 0 MAXSIZE DB 0 ; ; Encode a packet from memory contents instead of from a file ; ENCSTR EQU $ PUSH HL ;Save the registers PUSH BC PUSH DE LD (MEMSTR),HL ;Store the passed pointer CALL RSETPKT ;Reinitiaize GETPKT() parameters CALL GETPKT ;Get a packet LD HL,0 ;Reset the memory pointer LD (MEMSTR),HL POP DE ;Restore the registers POP BC POP HL RET ;Return to the caller ; ; Get a packet worth of data from the FILE indicated by the global ; FCB. Eighth bit quoting, and Repeat count prefixing are done ; as indicated by the status of EBQFLAG, and RPTFLG respectively. ; GETPKT EQU $ PUSH BC ;Save the registers PUSH DE PUSH HL LD A,(CURCHK) ;Calculate the size of a packet SUB '1' LD B,A LD A,(SPSIZ) ;Get the user specified size SUB 5 ;Minus the overhead SUB B LD (MAXSIZE),A ;Save it for later use LD HL,(NEXT) ;Get the next character, 16 bits LD BC,0 ;Subtract zero to set flags OR A ;Reset the carry flag SBC HL,BC ;Set the flags JP P,GETPKT1 CALL GETCH ;Get a character if no previous exists LD (CH),HL ;Save it GETPKT1 EQU $ LD BC,0 ;Copy leftovers from previous call GETPKT2 EQU $ LD HL,LEFTOVER ;Get the start ADD HL,BC ;Index by BC LD A,(HL) ;Get a byte LD HL,FILBUF ;Get the destination ADD HL,BC ;Index by BC LD (HL),A ;Put a byte IFZ GETPKT3 ;Exit loop if zero byte found INC C ;Point to next JR GETPKT2 ;Loop on GETPKT3 EQU $ LD A,C ;Save the initial size of leftovers LD (SIZE),A XOR A ;Nullify the string for next time LD (LEFTOVER),A GETPKT4 EQU $ LD HL,(CH) ;Get the character LD BC,0 ;Subtract zero to set the flags OR A SBC HL,BC JP M,GETPKT20 ;Jump at end of file CALL GETCH ;Get the next character LD (NEXT),HL ;Save it LD A,(SIZE) ;Get the current size LD (OSIZE),A ;Save it in case we overflow the packet LD C,A ;Make BC a 16 bit value of C LD B,0 LD HL,FILBUF ;Get the desination buffer ADD HL,BC ;Index by BC LD (CBFPTR),HL ;Save the buffer pointer LD HL,(CH) ;Get the character LD A,L ;Keep only 8 bits CALL ENCODE ;Encode it and store the result LD HL,(CBFPTR) ;Compute the new size LD BC,FILBUF ;Get the start OR A ;Reset carry SBC HL,BC ;Compute lenght LD A,L ;Keep only 8 bits LD (SIZE),A ;Store the result LD HL,(NEXT) ;Get the next character LD (CH),HL ;Store it as the current character LD A,(SIZE) ;Get the size and check the size LD C,A LD A,(MAXSIZE) ;Get the maximum length CP C ;Are they equal? JP Z,GETPKT20 ;Go return SIZE if equal JP P,GETPKT13 ;Jump if maxsize still bigger LD BC,0 ;Start from the beginning GETPKT11 EQU $ LD A,(OSIZE) ;Get the oldsize index PUSH BC ;Save the value of i ADD A,C ;Compute osize+i LD C,A ;Save the result LD HL,FILBUF ;Get the start of the buffer ADD HL,BC ;Compute &filbuf[osize+i] LD A,(HL) ;Get the character stored there POP BC ;Restore i LD HL,LEFTOVER ;Get the address of the leftover buffer ADD HL,BC ;Compute the absolute address LD (HL),A ;Store the byte OR A ;Check the value for zero JR Z,GETPKT12 ;Jump if end of string INC C ;Compute i++ JR GETPKT11 ;Go to the top of the loop GETPKT12 EQU $ LD A,(OSIZE) ;Store the new pointer LD (SIZE),A LD C,A ;Terminate the string with a NULL LD B,0 ;Get a 16 bit offset LD HL,FILBUF ;Get the starting address ADD HL,BC ;Compute the address LD (HL),0 ;Put in the NULL JP GETPKT20 ;Go to the return code GETPKT13 EQU $ JP GETPKT4 GETPKT20 EQU $ LD A,(SIZE) ;Get the size to return POP HL ;Restore the registers POP DE POP BC RET ; ; Encode the character in the Accumlator and put it into ; the packet buffer at CBFPTR. ; ENCODE EQU $ PUSH BC ;Save the regs PUSH DE PUSH HL LD C,A ;Save the character to encode LD A,(RPTFLG) ;Is repeat quoting in effect? OR A JP Z,ENCODE30 LD HL,(NEXT) ;Get the last character LD A,L IFANOT C,ENCODE3 LD A,(RPTCNT) ;Get the current repeat count INC A ;Add one to it LD (RPTCNT),A ;Store it back CP 94 ;Too many characters? JP M,ENCODE50 LD A,(RPTQ) CALL PUTCBF LD A,(RPTCNT) TOCHAR CALL PUTCBF XOR A LD (RPTCNT),A JP ENCODE30 ENCODE3 EQU $ LD A,(RPTCNT) IFANOT 1,ENCODE7 XOR A LD (RPTCNT),A LD A,C ;Get the character back CALL ENCODE ;Encode it again LD HL,(CBFPTR) ;Get the buffer pointer LD DE,FILBUF ;Get the start of the buffer OR A ;Reset the carry SBC HL,DE ;Compute the difference in L LD A,(MAXSIZE) ;Get MAXSIZE CP L ;Is L <= A? JP M,ENCODE6 LD A,L ;Get SIZE LD (OSIZE),A ;Store it in the old size ENCODE6 EQU $ XOR A LD (RPTCNT),A LD A,C ;Get the character back CALL ENCODE ;Encode it JP ENCODE50 ENCODE7 EQU $ LD A,(RPTCNT) CP 2 JP M,ENCODE10 LD A,(RPTQ) CALL PUTCBF LD A,(RPTCNT) ;Get the count ADD A,' '+1 ;Uncontrolify it CALL PUTCBF XOR A LD (RPTCNT),A ENCODE10 EQU $ ENCODE30 EQU $ LD A,C ;Get the character AND 127 ;Turn off high bit LD B,A ;Save it LD A,C ;Get the character AND 128 ;Leave only high bit LD D,A ;Save it IFZ ENCODE32 LD A,(EBQFLG) IFZ ENCODE32 LD A,(EBQ) CALL PUTCBF LD C,B ;Save only 7 bit version ENCODE32 EQU $ LD A,C ;Get all bits for check IFA 127,ENCODE33 IFAGE ' ',ENCODE34 ENCODE33 EQU $ LD A,(MYCTLQ) CALL PUTCBF LD A,C ;Get the character ADD A,64 ;Uncontrolify it AND 127 ;Keep only 7 bits LD C,A ;Save the new value ENCODE34 EQU $ LD HL,(CBFPTR) ;Do this ahead to save overhead LD A,(MYCTLQ) IFANOT B,ENCODE35 PUTHL A ;Store the byte ENCODE35 EQU $ LD A,(RPTFLG) IFZ ENCODE36 LD A,(RPTQ) IFANOT B,ENCODE36 LD A,(MYCTLQ) PUTHL A ENCODE36 EQU $ LD A,(EBQFLG) IFZ ENCODE37 LD A,(EBQ) IFANOT B,ENCODE37 LD A,(MYCTLQ) PUTHL A ENCODE37 EQU $ PUTHL C LD (CBFPTR),HL LD (HL),0 ENCODE50 EQU $ POP HL ;Restore the stack POP DE POP BC RET ; ; Decode the contents of the packet, and output them using ; the function whose address is passed in HL ; DECODE LD (OUTADDR),HL ;Save the output function PUSH BC ;Save the registers that we use PUSH DE PUSH HL LD HL,DATA ;Get the buffer address LD (DATPTR),HL ;Set the address LD C,A ;Get the length LD B,0 ;Make it 16 bits PUSH HL ;Save DATPTR ADD HL,BC ;Compute the end of the packet LD (HL),0 ;Put in the NULL byte POP HL ;Get DATPTR back DECODE0 LD A,1 ;Set the repeat count LD (RPTCNT),A LD A,(HL) ;Get a character INC HL ;Point to the next LD C,A ;Store the value OR A ;Is it NULL? JP Z,DECODE40 ;Quit the loop if it is LD A,(RPTFLG) ;Is repeat prefixing on? IFZ DECODE1 LD A,(RPTQ) ;Get the quote character IFANOT C,DECODE1 LD A,(HL) ;Get the count + 32 SUB ' ' ;Make it the real count INC HL ;Point to next character LD (RPTCNT),A ;Save the repeat count LD A,(HL) ;Get a character INC HL ;Point to the next LD C,A ;Save the character DECODE1 XOR A ;Set the initial eighth bit as ZERO LD D,A LD A,(EBQFLG) ;Is eighth bit quoting on? IFZ DECODE2 LD A,(EBQ) ;Get the eighth bit quote character IFANOT C,DECODE2 LD D,128 ;Get an eighth bit LD A,(HL) ;Get a character INC HL ;Point to the next LD C,A ;Save the character DECODE2 LD A,(MYCTLQ) ;Get the control character quote IFANOT C,DECODE5 LD A,(HL) ;Get a character INC HL ;Point to the next LD C,A ;Save the character AND 127 ;Keep 7 bits LD E,A ;Save only 7 bits worth LD A,E ;Check lower bound of controls CP '@' JP M,DECODE3 ;Jump if less than CP 96 ;Check upper bound of controls JP M,DECODE4 DECODE3 IFANOT '?',DECODE5 DECODE4 LD A,C ;Get the character SUB 64 ;Subtract 64 to uncontrolify it AND 127 LD C,A ;Save the new value DECODE5 LD A,D ;Get the eighth bit OR C ;Or in the character LD C,A ;Save the new value LD A,(RPTCNT) ;Get the repeat count LD B,A ;Get it into the counter DECODE8 LD IX,RTRANS ;Get the pointer CALL INCKTRANS ;Increment character counts LD A,C ;Get the character CALL PUTCH JR NZ,DECODE50 DJNZ DECODE8 ;Loop until done JP DECODE0 DECODE40 EQU $ POP HL ;Restore the stack POP DE POP BC RET DECODE50 EQU $ CALL XERROR0 ;Print a system error message LD A,1 ;Set NZ status for return OR A JR DECODE40 ;Join the exit code ; ; Get the next character from the input file. We translate CR to ; CRLF, for ASCII files. Returns with (EOFLAG) set to 0FFH at end ; of file. The character retrieved is in HL. HL will be 16bits ; of -1 and EOF, but will otherwise only be 8bits wide. H in this ; case will always be 0, and L will hold the character. ; GETCH LD A,(FILTYPE) ;Check for binary mode OR A ;Set the flags JR NZ,GETCH1 ;Jump if it is binary LD A,(PREVCH) ;Get the previous character IFANOT CR,GETCH1 LD A,10 ;Get a LF character LD (PREVCH),A ;Reset the previous character LD L,A ;Put it into HL LD H,0 RET ;Return to the caller GETCH1 EQU $ LD HL,(MEMSTR) LD A,H OR L JR Z,GETCH2 LD A,(HL) INC HL LD (MEMSTR),HL IFZ GETCH4 JR GETCH3 GETCH2 EQU $ LD DE,FCB ;Get the File Control Block CALL XGET ;Get a character into A JR NZ,GETCH4 ;Jump to EOF on error LD IX,STRANS ;Get the pointer CALL INCKTRANS ;Increment the character count GETCH3 EQU $ LD (PREVCH),A ;Set the previous character LD L,A ;Put it into HL LD H,0 RET ;Return GETCH4 EQU $ LD A,0FFH ;Set the EOF flag LD (EOFLAG),A LD (PREVCH),A ;Reset the previous character flag LD L,A ;Make HL 16bits wide -1 LD H,A RET ;Return to caller ; ; Put the next character to the output file. We convert CRLF to CR ; IFF X packets are not active, and binary mode is not active ; PUTCH PUSH HL PUSH BC ;Save the register LD C,A ;Save the character to output LD A,(PREVCH) ;Get the previous character IFANOT CR,PUTCH1 LD A,(DISFLG) ;Check if we are doing X packets IFZ PUTCH1 LD A,(FILTYPE) ;Doing D packets, so check file mode OR A JR NZ,PUTCH1 LD A,C IFA 10,PUTCH2 PUTCH1 LD A,C ;Get the character to output LD (PREVCH),A ;Make it the new previous LD HL,(OUTADDR) ;Get the output routines address CALL CALLHL ;Call the output routine PUTCH2 POP BC ;Restore the stack POP HL RET ;Return to caller ; ; Put A into the location pointed to by CBFPTR, and increment the ; pointer to point to the next location ; PUTCBF LD HL,(CBFPTR) ;Get the pointer PUTHL A LD (CBFPTR),HL ;Store the new pointer value RET ;Return ;end of file <<< m4rmt.asm >>> ; M4RMT/ASM ; REMOTE KERMIT COMMAND REMOTE LD A,CMKEY LD DE,RMTTAB CALL COMND JP KERMT2 LD C,A ;SAVE THE TYPE CALL NEWLIN LD B,0 LD HL,RMTJTB ;GET THE JUMP TABLE ADD HL,BC ;COMPUTE THE ADDRESS LD A,'G' LD (PKTTYPE),A ;Set to generic packet JP (HL) ; REMOTE COMMAND JUMP TABLE RMTJTB JP RMTCWD ;CHANGE WORKING DIRECTORIES JP RMTDEL ;DELETE A FILE JP RMTDIR ;DISPLAY A DIRECTORY JP RMTDSK ;DO A REMOTE DISK ALLOCATION JP RMTHLP ;GET REMOTE HELP JP RMTHST ;DO REMOTE HOST COMMAND JP RMTKER ;DO REMOTE KERMIT COMMAND JP RMTWHO ;RUN A REMOTE PROGRAM JP RMTREN ;SEND DATA TO A REMOTE PROGRAM JP RMTTYPE ;DISPLAY A REMOTE FILE JP RMTCOPY ;Copy a file JP RMTMSG ;Send a message JP RMTSET ;Set a variable JP RMTQUERY ;Query a variable JP RMTCLOSE ;Close the log JP RMTSEND ;Send the log JP RMTSTART ;Start logging JP RMTSTOP ;Stop logging JP RMTLOGIN ;Login to dedicated server JP RMTPRG ;Remote program manipulation JP RMTSRV ;Remote server status query ; ; DO A GENERIC REMOTE COMMAND ; GENCMD LD DE,RMTDATA ;Set the initial destination LD B,0 ;Set the initial counters LD (GENTYPE),A ;Save the type IFA 'J',GENCMD1 ;Jump if journaling IFANOT 'V',GENCMD2 ;Jump if not variable GENCMD1 LD A,C ;Get the second attribute LD (DE),A ;Store it INC DE ;Point ahead INC B ;Plus one for the extra attribute GENCMD2 LD C,0 ;Reset the beginning field length GENCMD3 LD (INITRMT),DE ;Save the values LD (INITCNT),BC CALL ENCFLDS ;Get the input fields GENCMD5 LD A,'1' ;SET CURRENT CHECK SUM LD (CURCHK),A XOR A ;Set the packet number to zero LD (ARGBLK),A NSTATE 'I' ;Set the state to I-initiate CALL INIT ;Initialize buffers LD HL,0 ;Set packet count to zero LD (NUMPKT),HL LD (NUMRTR),HL ;Reset number of retries XOR A ;Set mode to display on screen LD (DISFLG),A LD (PKTNUM),A ;Zero current packet number LD (NUMTRY),A ;Zero retries for current packet LD (CZSEEN),A CALL CLRPRT CALL PROTO JP KERMIT ; ; State G of the protocol. Build a G or C packet, and send it ; DOGEN EQU $ CALL CHKTRYS ;Check the retry count LD A,(PKTNUM) ;Set the packet number to current LD (ARGBLK),A LD HL,FILBUF ;Transfer data to the buffer LD DE,DATA ;Get the DATA area LD A,(PKTTYPE) ;Get the requested type, 'G' or 'C' IFA 'C',DOGEN6 ;If COMMAND then jump INC DE ;Point to data+1 if not remote host DOGEN6 LD A,(GENLEN) ;Get the length IFZ DOGEN1 ;Jump if no length LD C,A ;Make BC the count LD B,0 LDIR ;Move the bytes DOGEN1 LD C,A ;Store the length LD A,(PKTTYPE) ;Check the type again IFA 'C',DOGEN7 ;If COMMAND then jump LD A,(GENTYPE) ;Get the GENERIC type LD (DATA),A ;Store it INC C ;Add one to DATA length LD A,'G' ;Send a generic packet DOGEN7 PUSH AF ;Save the packet type LD A,C ;Get the length of DATA LD (ARGBLK+1),A ;Store it LD A,'1' ;Always 1 character checksum LD (CURCHK),A LD A,(CHKTYP) ;Get the desired checksum type LD (INICHK),A ;Save it for later POP AF ;Get the packet type back CALL SPACK ;Send the packet JP ABORT ;Abort on an error RPACKET ;Receive a packet IFANOT 'S',DOGEN2 ;Skip if not send_init LD A,(ARGBLK+1) ;Get the length LD HL,DATA ;Get the DATA area CALL SPAR ;Get parameters from packet LD HL,DATA ;Get the DATA area CALL RPAR ;Put our capabilities in LD (ARGBLK+1),A ;Store the length that is returned SPACKET 'Y' ;Send ACK with parameters LD A,(INICHK) ;Get the requested checksum type LD (CURCHK),A ;Store it as current NSTATE 'f' ;Set state to file receive RET ;Return to protocol switch DOGEN2 IFANOT 'X',DOGEN3 ;X packet? Jump if not CALL SETUPDIS ;Set up for terminal display CALL PRTPKTOUT ;Print the packet contents CALL DOINC ;Increment everything LD (ARGBLK+1),A ;A is zero, so use for zero length SPACKET 'Y' ;Send ACK NSTATE 'd' ;Set state to receive DATA RET ; DOGEN3 IFANOT 'Y',DOGEN4 ;Jump if not ACK CALL NEWLIN ;Get a new line for data CALL PRTPKTOUT ;Print the packets contents on screen NSTATE 'C' ;Set state to complete RET ;Return to proto switch ; DOGEN4 CP 'N' ;Was it NAK? RET Z ;If so, stay in this state IFANOT 'E',DOGEN5 ;If not Error packet, then go CALL ERROR ;Print error message CALL NEWLIN ;Get a new line JP KERMIT ;Get a new command ; DOGEN5 STROUT UNKNOWN ;Print unknown packet type message XOR A LD (ARGBLK+1),A ;Set DATA length to zero SPACKET 'E' ;Send an error packet JP KERMIT ;Get a new command ; ; Do remote directory ; RMTDIR EQU $ GENCASE 'D',1 ; ; Remote delete file ; RMTDEL EQU $ GENCASE 'E',1 ; ; Remote disk utilization ; RMTDSK EQU $ GENCASE 'U',1 ; ; Remote Help ; RMTHLP EQU $ GENCASE 'H',1 ; ; Remote Program control ; RMTPRG EQU $ GENCASE 'P',2 ; ; Remote Kermit Command ; RMTKER EQU $ GENCASE 'P',1 ; ; Remote type command ; RMTTYPE EQU $ GENCASE 'T',1 ; ; Remote who command ; RMTWHO EQU $ GENCASE 'W',2 ; ; Remote change directory ; RMTCWD EQU $ GENCASE 'C',2 ; ; Remote rename a file ; RMTREN EQU $ GENCASE 'R',2 ; ; Remote copy a file ; RMTCOPY EQU $ GENCASE 'K',2 ; ; Remote send a message ; RMTMSG EQU $ GENCASE 'M',2 ; ; Remote set a variable ; RMTSET EQU $ LD C,'S' GENCASE 'V',2 ; ; Remote query a variable ; RMTQUERY EQU $ LD C,'Q' GENCASE 'V',2 ; ; Remote close the log file ; RMTCLOSE EQU $ LD C,'c' GENCASE 'J',1 ; ; Remote send log file ; RMTSEND EQU $ LD C,'s' GENCASE 'J',1 ; ; Remote start logging ; RMTSTART EQU $ LD C,'+' GENCASE 'J',1 ; ; Remote stop logging ; RMTSTOP EQU $ LD C,'-' GENCASE 'J',1 ; ; Remote login ; RMTLOGIN EQU $ GENCASE 'l',3 ; ; Remote server status query ; RMTSRV EQU $ GENCASE 'Q',1 ; ; Remote host command ; RMTHST EQU $ LD DE,FILBUF LD A,CMTXT CALL COMND JP KERMT2 LD (TEMP4),A LD A,CMCFM CALL COMND JP KERMT3 LD A,(TEMP4) LD (GENLEN),A LD C,A LD B,0 LD HL,FILBUF ADD HL,BC LD (HL),0 LD A,1 LD (FLDLEN),A LD A,'C' LD (PKTTYPE),A JP GENCMD5 ; ; Get users response, and put it into the buffer ; ENCFLDS LD A,CMTXT LD DE,DATA ;Get the text CALL COMND JP KERMT2 CALL ENCOLEN ;Length encode each argument JP GETFIELD1 ;On error jump LD HL,RMTDATA ;Get the input buffer CALL ENCSTR ;Encode the contents LD A,(SIZE) ;Get the length LD (GENLEN),A ;Save it for later RET ;Return ; GETFIELD1 EQU $ ;Bad string found in encodelen STROUT TOOLONG ;Print string too long message JP KERMIT ;Abort completely ; ; Protocol switch code ; PROTO EQU $ LD A,(STATE) SWITCH 'D',SDATA ;Send data SWITCH 'F',SFILE ;Send file SWITCH 'T',SNDTRAN ;Transition from 'F' to 'D' SWITCH 'Z',SEOF ;Send EOF SWITCH 'S',SINIT ;Send init SWITCH 'B',SEOT ;End of transmittion SWITCH 'C',COMP ;Completed SWITCH 'A',SABORT ;Abort SWITCH 'd',RDATA ;Receive data SWITCH 'f',RFILE ;Receive file SWITCH 't',RECTRAN ;Transition from 'f' to 'd' SWITCH 'R',RINIT ;Receive init SWITCH 'r',RINITF ;Receive init with filename (GET command) SWITCH 'G',DOGEN ;Generic server command SWITCH 'I',IINIT ;Generic init packet CALL SABORT ;Bad protocol state JP KERMIT ;Abort ; ; SEND I-INITIATE ; IINIT CALL CHKTRYS ;Check retry threshold LD A,'1' ;RESET TO USE SINGLE CHARACTER CHECKSUM LD (CURCHK),A ;FOR STARTUP LD A,(CHKTYP) ;GET OUR DESIRED BLOCK CHECK TYPE LD (INICHK),A ;Store it as the initial value LD HL,DATA ;GET A POINTER TO OUR DATA BLOCK. CALL RPAR ;SET UP THE PARAMETER INFORMATION. LD (ARGBLK+1),A ;SAVE THE NUMBER OF ARGUMENTS. LD A,(PKTNUM) ;GET THE PACKET NUMBER. LD (ARGBLK),A SPACKET 'I' ;Send the I packet RPACKET ;Get the answer packet CP 'Y' ;Is it an ACK? JP NZ,IINIT3 ;IF NOT TRY NEXT. CALL CHKBLK RET NZ ;IF NOT TRY AGAIN. CALL DOINC LD A,(ARGBLK+1) ;GET THE NUMBER OF PIECES OF DATA. LD HL,DATA ;POINTER TO THE DATA. CALL SPAR ;READ IN THE DATA. LD A,(INICHK) ;GET THE AGREED UPON BLOCK-CHECK-TYPE LD (CURCHK),A ;STORE AS TYPE TO USE FOR PACKETS NOW NSTATE 'G' RET IINIT3 IFANOT 'N',IINIT4 ;NAK? CALL UPDRTR ;UPDATE THE NUMBER OF RETRIES. RET IINIT4 CP 'E' ;IS IT AN ERROR PACKET. JP NZ,ABORT ;JUMP IF NOT LD A,80 ;SET UP ALL DEFAULT PARAMETERS LD (SPSIZ),A XOR A LD (SPAD),A LD (SPADCH),A LD A,13 LD (SEOL),A LD A,'1' LD (CURCHK),A LD A,'#' LD (SQUOTE),A NSTATE 'G' RET ; ; This routine encodes the length of the blank separated fields ; into a packet for the generic routines. If there are more ; blank separated fields than FLDLEN says there should be, the ; remaining fields are added to the end of the last field, ; separated by blanks. ; ENCOLEN LD HL,DATA ;Get the source LD DE,(INITRMT) ;Get the initial location LD BC,(INITCNT) ;Get the initial counters PUSH DE ;Save the store address for length PUSH BC INC DE ;Point to where the data goes LD A,(FLDLEN) ;Get the number of fields LD B,A ;Put it into the counter POP AF ;Get the initial length LD (FLDLEN),A ;Set the length to zero initially ENCLEN1 LD A,(HL) ;Get a character IFANOT 20H,ENCLEN4 ;Jump if not space ENCLEN2 INC HL ;Point to next character IFA (HL),ENCLEN2 ;Loop while we are looking at a space DJNZ ENCLEN3 ;See if we have done all fields INC B ;Reset the counter back to one if so LD (DE),A ;Store a space INC DE ;Point to next place to store at INC C ;Increment the field length JR ENCLEN1 ;Process next character ENCLEN3 LD A,C ;Get the field length TOCHAR ;Make it printable EX (SP),HL ;Get the store address for the length LD (HL),A ;Store the length byte POP HL ;Restore the old HL PUSH DE ;Save the new length byte address INC DE ;Point to the data store address LD C,0 ;Reset the count of characters LD A,(FLDLEN) ;Get the total length INC A ;Add one to the length LD (FLDLEN),A ;Store the new length JR NZ,ENCLEN1 ;Continue if OK POP DE ;Restore the stack RET ;Return error ENCLEN4 JR C,ENCLEN5 ;If this is a control character then stop INC C ;Correct for the comming decrement LDI ;Move one char, and increment counter INC C ;Plus one more for the length LD A,(FLDLEN) ;Get the length INC A ;Add one for current character LD (FLDLEN),A ;Store the new length JR NZ,ENCLEN1 ;Top of the loop if no overflow POP DE ;Restore the stack RET ;Return error ENCLEN5 POP HL ;Get the length address LD A,C ;Get the length TOCHAR ;Make it printable LD (HL),A ;Store this fields length XOR A ;Terminate the packet LD (DE),A LD A,(FLDLEN) ;Get the overall length LD (GENLEN),A ;Save it for later OR A ;Is it a null length string? JP Z,RSKP ;Return if it is INC A ;Add one to length for field length byte CP MAXPKT-4 ;Too big for packet? RET P ;Return error if string too long LD (GENLEN),A ;Save it JP RSKP ;Return to the caller ;end of file <<< m4send.asm >>> ; M4SEND/ASM ; ; SEND COMMAND ; SEND EQU $ CALL NEWLIN LD A,CMTXT ;PARSE A TEXT STRING LD DE,MFNBUF ;GIVE THE ADDRESS FOR THE STRING PUSH DE ;Save it CALL COMND ;GET THE INPUT JP KERMT2 ;GIVE UP ON BAD PARSE. POP HL ;Get the pointer LD (MFNPTR),HL ;Save it as the start LD A,1 ;Set the log names flag LD (LOGNAMES),A CALL BUILDF ;Build a list doing wildcarding LD A,(FILECNT) ;Get the number of files IFNZ SEND11 ;Jump if some files were found STROUT NOFILES ;Print the message JP KERMIT SEND11 LD (MFNPTR),HL ;Save the start of the found list CALL MFNAME ;Get the next from the list JR NC,SEND14 ;Jump if got a name CALL NEWLIN LD A,19 ;Issue system error, Illeagal filename CALL XERROR JP KERMIT ;GET A NEW COMMAND SEND14 CALL INIT ;Clear the line and initialize buffers XOR A LD (PKTNUM),A LD (NUMTRY),A ;SET THE NUMBER OF TRIES TO ZERO. LD HL,0 LD (NUMPKT),HL ;SET THE NUMBER OF PACKETS TO ZERO. LD (NUMRTR),HL ;SET THE NUMBER OF RETRIES TO ZERO. LD (KTRANS),HL LD A,'1' ;RESET TO USE SINGLE CHARACTER CHECKSUM LD (CURCHK),A ;FOR STARTUP NSTATE 'S' LD (DISFLG),A ;Put in something non zero CALL CONDCHR ;Display starting sendinit character 'S' CALL CLRPRT ;CLEAR OUT ANY STACKED NAKS STROUT HELPMSG CALL PROTO ;Do protocol states JP KERMIT ;Return to Kermit ; ; SEND ROUTINES ; SEND INITIATE ; SINIT CALL CHKTRYS ;Check retry threshold LD A,'1' ;RESET TO USE SINGLE CHARACTER CHECKSUM LD (CURCHK),A ;FOR STARTUP LD A,(CHKTYP) ;GET OUR DESIRED BLOCK CHECK TYPE LD (INICHK),A LD HL,DATA ;GET A POINTER TO OUR DATA BLOCK. CALL RPAR ;SET UP THE PARAMETER INFORMATION. LD (ARGBLK+1),A ;SAVE THE NUMBER OF ARGUMENTS. LD A,(NUMPKT) ;GET THE PACKET NUMBER. LD (ARGBLK),A SRPACK 'S' ;Do send init, and get response IFANOT 'Y',SINIT3 ;Was it an ACK? Jump if not CALL CHKBLK RET NZ ;IF NOT TRY AGAIN. CALL DOINC ;Increment and reset LD A,(ARGBLK+1) ;GET THE NUMBER OF PIECES OF DATA. LD HL,DATA ;POINTER TO THE DATA. CALL SPAR ;READ IN THE DATA. LD A,(INICHK) ;GET THE AGREED UPON BLOCK-CHECK-TYPE LD (CURCHK),A ;STORE AS TYPE TO USE FOR PACKETS NOW NSTATE 'F' ;Set the state CALL CONDCHR CALL GETFIL ;Open the file name given in FCB JP SNDABORT ;Something is wrong if come to here RET ;Next state in protocol ; ; Come here on bad answer to S packet ; SINIT3 CP 'N' ;NAK? JP NZ,BADERROR ;If not, then it is a fatal error CALL CONDCHR ;Output N character RET ;Back to protocol ; ; Terminate a transaction log because of an error ; ; ; SEND FILE HEADER ; SFILE CALL CHKTRYS ;Check retry threshold XOR A ;CLEAR A LD (CZSEEN),A LD DE,DATA ;GET A POINTER TO OUR DATA BLOCK. LD HL,MFREQ ;Get filename LD BC,255 ;B must be zero, C must be big for LDI SF1 LD A,(HL) IFA '/',SF2 IFA ':',SF4 IFALT ' ',SF4 LDI INC B JR SF1 SF2 LD (HL),'.' LDI INC B SF3 LD A,(HL) IFALT ' ',SF4 IFA ':',SF4 LDI INC B JR SF3 SF4 EQU $ LD (DATPTR),DE LD (FCBPTR),HL LD A,B ;NUMBER OF CHAR IN FILE NAME. LD (ARGBLK+1),A EX DE,HL LD (HL),EOS ;Put in the print terminator LD A,(PKTNUM) ;GET THE PACKET NUMBER. LD (ARGBLK),A SRPACK 'F' ;Send file header and get response IFANOT 'Y',SFILE2 ;Jump if not an ACK CALL CHKBLK ;Check packet number RET NZ ;Return if not the right one SFIL14 CALL DOINC ;Increment packet count SFIL15 CALL RSETPKT ;Reinitialize GETPKT() CALL GTCHR JP SFIL16 ;ERROR GO SEE IF ITS EOF. JR SFIL17 ;GOT THE CHARS, PROCEED. SFIL16 CP 0FFH ;IS IT EOF? JP NZ,SNDABORT ;IF NOT GIVE UP. NSTATE 'Z' ;Set EOF state CALL CONDCHR RET SFIL17 EQU $ NSTATE 'T' ;Set state to data send LD (DISFLG),A ;Make sure display is on RET SFILE2 CP 'N' ;NAK? JP NZ,BADERROR ;TRY IF ERROR PACKET. CALL CONDCHR ;Display the packet character CALL CHKBLKINC ;Check NAK for packet N+1 RET NZ ;If not, then try to resend JR SFIL14 ;As good as an ACK, join the ack code ; ; Send transition state from Send file to Send data ; SNDTRAN EQU $ STROUT KERSND ;Print SENDING message STROUT TFILNAM ;Print the file name LD A,(TRANLOG) ;Check if logging active IFZ SNDTRAN2 ;If not, then jump LD DE,TRFCB ;Get the log file FCB TRLOG KERSND,SNDTRAN1 ;Log the SENDING=> message TRLOG TFILNAM,SNDTRAN1 ;Log the file name TRLOG TIMEMES,SNDTRAN1;Log the time: message CALL PRTTIME ;Print the time JR SNDTRAN2 ;Join other code ; ; Close up on a logging error ; SNDTRAN1 EQU $ XOR A ;Reset the log open flag LD (TRANLOG),A LD DE,TRFCB ;Close the log file CALL XCLOSE SNDTRAN2 EQU $ NSTATE 'D' ;Set the state to SEND DATA RET ; ; SEND DATA ; SDATA CALL CHKTRYS ;Check the retry threshold LD DE,DATA ;Get the data area LD HL,FILBUF ;Get the file buffer LD A,(SIZE) ;Get the number of bytes encoded IFZ SDAT11 ;Jump if there are none LD C,A ;Put LSB into C LD B,0 ;Zero B LDIR ;Move the bytes SDAT11 LD A,(SIZE) ;Get the number of bytes back LD (ARGBLK+1),A ;Store it as the length LD A,(PKTNUM) ;Get the current packet number LD (ARGBLK),A ;Put it in the packet LD A,'D' ;Get the packet type CALL SPACK ;Send a data packet JP SNDABORT ;Abort if send fails LD A,(NUMPKT) ;See if time to log progress AND 3 ;Every 4 packets LD A,'.' ;Get the character CALL Z,CONDCHR ;Output if it is time RPACKET ;Get a packet IFANOT 'Y',SDATA2 ;Jump if not an ACK CALL CHKBLK ;See if proper packet number RET NZ ;Wait for more if not right number CALL DOINC ;Increment and reset LD A,(ARGBLK+1) ;Get the length of packet IFANOT 1,SDAT15 ;Jump if not 1 character LD A,(DATA) ;Get the character sent in ACK IFANOT 'Z',SDAT14 ;Is it end of file? Jump if not LD (CZSEEN),A ;Save it JR SDAT15 ;Continue SDAT14 IFANOT 'X',SDAT15 ;Was it EOT? Jump if not LD (CZSEEN),A ;Save it SDAT15 LD A,(CZSEEN) ;Get the character IFZ SDAT12 ;Jump if nothing there CALL CONDCHR ;Display the character NSTATE 'Z' ;Set the state to EOF RET ;Return to protocol ; SDAT12 CALL GTCHR ;Get more data from input file JP SDAT13 ;Jump if error occurs (might be EOF) RET ;Continue sending ; SDAT13 CP 0FFH ;Was the file error EOF? JP NZ,SNDABORT ;If not, then file error, so abort NSTATE 'Z' ;Set state to EOF CALL CONDCHR ;Output the state RET ;Return to protocol ; SDATA2 CP 'N' ;Is it a NAK? JP NZ,BADERROR ;Nope, check next type CALL CONDCHR ;Display packet type CALL CHKBLKINC ;NAK this packet plus one? JR Z,SDAT12 ;Just as good as an ACK, Join ACK code. CALL UPDRTR RET ; ; Send the EOF packet ; SEOF CALL CHKTRYS ;Check the retry threshold CALL INITBLK ;Initialize ARGBLK LD A,(CZSEEN) ;Check for ABORT IFZ SEOF14 ;If not aborted, then keep going LD A,(TRANLOG) ;Check if logging active IFZ SEOF10 ;Jump if no logging LD DE,TRFCB ;Get the log file FCB TRLOG TRANCANC,SEOF19 ;Log the canceled message SEOF10 LD A,(DISCARD) ;Should the file be deleted? IFZ SEOF11 ;Skip delete if user want to keep it LD A,'D' ;Tell other end to discard packet LD (DATA),A ;Store the delete character LD A,1 ;Length is one character SEOF11 LD (ARGBLK+1),A ;Store the length SEOF14 SRPACK 'Z' ;Send EOF, and get a response IFANOT 'Y',SEOF2 ;Jump if not an ACK CALL CHKBLK ;Check the packet number RET NZ ;Return if not correct one SEOF12 CALL DOINC ;Increment and reset CALL CHKFCB ;Check for file, don't close *SO CALL Z,XCLOSE ;Conditionally close it LD A,(CZSEEN) ;Did the user force us to stop? IFA 'Z',SEOF13 ;Jump if EOF was signaled by user CALL MFNAME ;Get a new file name JR C,SEOF13 ;Jump if no more CALL GETFIL ;AND OPEN IT JP SNDABORT ;SOMETHING IS WRONG, DIE. XOR A ;CLEAR A LD (CZSEEN),A NSTATE 'F' ;Set state to file send CALL CONDCHR LD IX,STRANS ;Update transmission information CALL UPDTRANS RET ;Continue protocol ; SEOF13 NSTATE 'B' ;Set state to EOT CALL CONDCHR LD IX,STRANS ;Update the transmission info CALL UPDTRANS RET ; SEOF2 CP 'N' ;NAK? JP NZ,BADERROR ;TRY AND SEE IF ITS AN ERROR PACKET. CALL CONDCHR CALL UPDRTR ;UPDATE THE NUMBER OF RETRIES. CALL CHKBLKINC RET NZ ;IF NOT GO TRY AGAIN. JR SEOF12 ;Just as good as an ACK ; SEOF19 XOR A ;Reset the log open flag LD (TRANLOG),A LD DE,TRFCB ;Close the file CALL XCLOSE JP SEOF10 ;Join other code ; ; Send EOT packet ; SEOT CALL CHKTRYS ;Check the retry threshold CALL INITBLK ;Initialize ARGBLK SRPACK 'B' ;Send END of BATCH and get response IFANOT 'Y',SEOT2 ;Jump if not ACK CALL CHKBLK ;Check the packet number RET NZ ;Return if not correct SEOT12 CALL DOINC ;Increment and reset NSTATE 'C' ;Set state to complete RET SEOT2 CP 'N' ;NAK? JP NZ,BADERROR ;IS IT ERROR. CALL CONDCHR CALL UPDRTR ;UPDATE THE NUMBER OF RETRIES. CALL CHKBLKINC JP Z,SEOT12 ;Good as an ACK, so continue OR A ;Is the other end starting over? JR Z,SEOT12 RET ; ; Check the retry threshold ; CHKTRYS EQU $ ;Check retry threshold LD A,(MAXTRY) ;Get the maximum LD B,A ;Save LD A,(NUMTRY) IFALT B,CHKTRYS1 ;Jump if not at limit POP DE ;Remove the callers return addr LD DE,ERMS14 ;Print the error message CALL ERROR3 JP SNDABORT ;CHANGE THE STATE TO ABORT. CHKTRYS1 EQU $ IFZ CHKTRYS2 ;Jump if first try PUSH AF ;Save the count LD A,'%' ;Print retrying message CALL CONDCHR POP AF ;Get the count back CHKTRYS2 EQU $ INC A ;Increment it LD (NUMTRY),A ;Save the new count RET ; ; Increment the packet count modulo 64, A already has the old one. ; INCPKT INC A AND 3FH LD (PKTNUM),A RET ; ; Move numtry to oldtry and zero numtry ; NUM2OLD EQU $ LD A,(NUMTRY) ;GET THE NUMBER OF TRIES. LD (OLDTRY),A ;SAVE IT. XOR A LD (NUMTRY),A ;RESET THE NUMBER OF TRIES. RET ; ; Increment display packet count ; INCDISPKT EQU $ LD HL,(NUMPKT) INC HL LD (NUMPKT),HL RET ; ; Do several things ; DOINC CALL INCPKT CALL INCDISPKT JP NUM2OLD ; ; Check the packet number 'received plus 1' verses that sent ; return their relation, eg <, >, =, <>. This is used as a ; method to determine that a NAK for packet N+1 is equivelent ; to an ACK for packet N. ; CHKBLKINC EQU $ LD A,(PKTNUM) ;Get the current packet number INC A ;Plus one LD B,A ;Save it LD A,(ARGBLK) ;Get the packet number returned CP B ;Are they equal? RET ;Return the flags setting ; ; Conditionally display the character in A based on the value ; of DISFLG. This is used to print the characters during transfers ; that show the status of the transfer. eg '.', 'Q', 'S', 'Z', etc ; CONDCHR EQU $ LD C,A ;Save the character LD A,(DISFLG) ;Check if should display the character OR A ;Set the flags RET Z ;Return if flag not set LD A,C ;Get the character back JP CONOUT ;Print the terminal on the console ; RSETPKT EQU $ XOR A ;GET A ZERO. LD (EOFLAG),A ;INDICATE NOT EOF. LD (SIZE),A ;Nothing in packet buffer LD (OSIZE),A ;No old length LD (LEFTOVER),A ;No leftovers from previous packet LD (RPTCNT),A ;No repeated characters yet LD (PREVCH),A ;Reset any previous character knowledge LD HL,-1 ;Set NO next character LD (NEXT),HL LD (CH),HL RET ; BADERROR EQU $ CP 'E' ;IS IT AN ERROR PACKET. JP NZ,SNDABORT CALL ERROR JP SNDABORT ; INITBLK EQU $ LD A,(PKTNUM) ;GET THE PACKET NUMBER. LD (ARGBLK),A XOR A LD (ARGBLK+1),A ;NO DATA. RET PRTTIME EQU $ PUSH AF ;Save the regs PUSH BC PUSH HL PUSH DE ;Save the FILE FCB LD HL,CLBUF ;Get the character buffer PUSH HL ;Save the address CALL XTIME ;Get the time LD (HL),CR ;Get a new line INC HL ;Point to next pos LD (HL),EOS ;Terminate the string POP HL ;Get the string to print back POP DE ;Get the log file FCB CALL OUTLOG CALL TIMCLOSE ;Close up if error occurs POP HL ;Restore the regs POP BC POP AF RET ; TIMCLOSE EQU $ XOR A ;Reset the file open flag LD (LOGTRAN),A LD DE,TRFCB ;Get the FCB JP XCLOSE ;Close the file and return. ; end of file <<< m4set.asm >>> ; m4set/asm ; ;THIS IS THE SET COMMAND. ; SETCOM LD DE,SETTAB ;Parse a keyword for set table LD A,SHLEN/3 ;Patch the number in the table LD (SETTAB),A ;Store the value LD A,MXSLEN ;Patch the other value LD (SETTAB+1),A LD A,CMKEY ;Select keyword parse CALL COMND ;Parse it JP KERMT2 ;Quit on an error LD HL,SETJTB ;Get the jump table address. LD C,A LD B,0 ADD HL,BC JP (HL) ;SET COMMAND JUMP TABLE SETJTB JP ESCAPE ;SET ESC JP LOCAL ;SET LOCAL JP SETEIGHT ;SET EIGHT-BIT-QUOTING JP SETFILE ;SET FILE JP SETBLK ;SET BLOCK-CHECK-TYPE JP SETEMUL ;SET emulation JP PRINTR ;set printer JP SETBUG ;SET DEBUG JP SETDSK ;SET DEFAULT DISK JP SETBEL ;SET BELL ON OR OFF JP SETSND ;SET SEND PARAMETERS JP SETREC ;SET RECEIVE PARAMTERS JP SETKEY ;SET A KEY FOR TRANSLATION JP SETFLO ;SET FLOW CONTROL JP SETINP ;SET INPUT PARAMETERS JP SETOTP ;SET OUTPUT PARAMETERS JP SETTAK ;Set take display SHLEN EQU $-SETJTB ;OFFSET FOR SHOW ALL ; ; Set file dispostion ; SETDISP LD DE,DISPTAB ;Get the parse table LD A,CMKEY CALL COMND ;Parse a keyword JP KERMT2 LD (TEMP1),A ;Save it LD A,CMCFM ;Get a confirm CALL COMND JP KERMT3 LD A,(TEMP1) LD (DISCARD),A ;Set the value JP KERMIT ; ; Set take file display ; SETTAK SETFLG TAKLOG ; ; Set input options ; SETINP LD A,CMKEY ;GET A KEYWORD LD DE,INPTAB ;WHERE ARE THE KEYWORDS AT? CALL COMND JP KERMT2 ;QUIT ON AN ERROR LD C,A IFANOT 0,STINP1 ;Check for first time SETFLG CSEFLG STINP1 CP 3 JP NZ,KERMT3 SETFLG INDSP ; ; Set output option ; SETOTP LD A,CMKEY LD DE,OUTTAB CALL COMND JP KERMT2 LD C,A IFANOT 0,STOTP1 SETFLG ECHFLG STOTP1 CP 3 JP NZ,KERMT3 SETFLG OTDSP ; ; Set flow control option ; SETFLO LD DE,FLOTAB LD A,CMKEY CALL COMND JP KERMT2 LD (TEMP1),A LD A,CMCFM CALL COMND JP KERMT3 LD A,(TEMP1) LD (FLOFLG),A ;STORE THE NEW STATUS JP KERMIT ; ; Set bell on/off ; SETBEL SETFLG BELFLG ;Set the bell ON or OFF ; ; Set block check type ; SETBLK LD DE,BLKTAB ;GET THE BLOCK-CHECK TABLE LD A,CMKEY ;PARSE A KEYWORD CALL COMND ;GO GET IT JP KERMT2 ;COULDN'T, COMPLAIN LD (TEMP1),A ;SAVE THE PARSED ITEM LD C,A LD A,CMCFM ;WANT TO END THE COMMAND CALL COMND ;GO DO IT JP KERMT3 ;GIVE UP LD A,(TEMP1) ;GET THE VALUE BACK LD (CHKTYP),A ;SAVE DESIRED CHECKSUM TYPE JP KERMIT ;GO GET ANOTHER COMMAND ; ; Set send options ; SETSND XOR A ;SET SEND/RECEIVE TO SEND JR SETSOR ; ; Set receive options ; SETREC LD A,1 ;SET SEND/RECEIVE TO RECEIVE ; ; Common code that uses the contents of A at this point to ; control where the set value is stored. All of the SEND/RECV ; options are set up in memory together, so that to give a ; particular send option a value, it is stored directly. The ; corresponding recv option is one byte in memory beyond the ; send option, so the flag (What is in A) is checked, and the ; destination address is incremented if A is non zero ; ; Memory looks like this ; ; SEOL DB 13 ; REOL DB 13 ; SSOH DB 1 ; RSOH DB 1 ; SETSOR LD (SORFLG),A ;STORE THE FLAG LD DE,STSNTB ;GET THE PARSE TABLE LD A,CMKEY CALL COMND ;PARSE SOMETHING JP KERMT2 ;ABORT LD HL,STSJTB ;GET THE JUMP TABLE LD C,A LD B,0 ADD HL,BC JP (HL) STSJTB JP STPDCH ;SET PAD CHARACTER JP STPAD ;SET PADDING ON/OFF JP SSOFP ;SET START OF PACKET JP STIMEO ;SET TIME OUT JP SSEOL ;SET END OF LINE JP SSQUOT ;SET QUOTE CHARACTER JP SSTURN ; ; Set the padding. Note that it is only done on output, so ; SET RECEIVE PADDING doesn't make sense. ; STPAD LD A,CMNUM ;GET A LENGTH COUNT CALL COMND ;PARSE A VALUE JP KERMT3 ;NOT CONFIRMED ON AN ERROR OR A ;CHECK FOR NO NUMBER JP Z,KERMT2 ;SAY AMBIGUOUS LD A,D ;CHECK FOR OVERFLOW IFZ STPD10 ;Go if none LD DE,OUTRNG CALL PRTSTR JP KERMIT STPD10 LD A,E LD (SPAD),A ;SET THE STATUS JP KERMIT ;GET A NEW COMMAND ; ; Set the padding character. Also applys to SEND only! ; STPDCH LD HL,SPADCH ;GET THE ADDRESS TO STORE AT SOR010 LD (SORLOC),HL ;SAVE IT FOR LATER LD A,CMNUM ;GET A DECIMAL NUMBER CALL COMND JP KERMT3 OR A ;CHECK FOR NO NUMBER JP Z,KERMT2 ;SAY AMBIGUOUS LD A,D ;CHECK FOR TOO BIG IFZ PDCH2 ;Go if ok LD DE,OUTRNG ;VALUE OUT OF RANGE ERROR CALL PRTSTR ;PRINT IT JP KERMIT PDCH2 LD HL,(SORLOC) ;GET WHERE TO PUT IT LD A,(SORFLG) ;GET THE MODE, SEND/RECEIVE OR A ;CHECK FOR SET OR RESET FLAG CALL Z,SSVAL ;IF ZERO THEN SET RECEIVE VALUE CALL NZ,SRVAL ;ELSE SET THE SEND VALUE JP KERMIT ;GET A NEW COMMAND ; ; Set START-OF-PACKET (Start Of Header, SOH) ; SSOFP LD HL,SSOHCH JP SOR010 ; ; Set turn around character ; SSTURN LD HL,STURN JP SOR010 ; ; Set time-out value ; STIMEO LD HL,STIME JP SOR010 ; ; Set End Of Line (or End Of Packet) character ; SSEOL LD HL,SEOL JP SOR010 ; ; Set eighth bit quote character ; SSQUOT LD HL,SQUOTE JP SOR010 ; ; Convert ASCII Decimal string to binary in BC, HL is the ; source buffer. ; DECHEX JP XDECHEX ; ; Store E at HL+1 ; SSVAL INC HL ; ; Store E at HL ; SRVAL LD (HL),E RET ; ; Convert contents of A to ASCII string, and display ; ANOUT PUSH HL LD L,A LD H,0 CALL NOUT POP HL RET ; ; Set the escape character ; ESCAPE LD A,CMCFM CALL COMND ;GET A CONFIRM. JP KERMT3 ;DIDN'T GET A CONFIRM. LD DE,ESCMES ;GET THE ADDRESS OF THE ESCAPE MESSAGE. CALL PRTSTR CALL XKEY LD (ESCCHR),A ;STORE THE NEW ESCAPE CHARACTER. CALL ESCPR ;Print the Verbpse description of it JP KERMIT ; ; Set local echo status ; LOCAL SETFLG ECOFLG ; ; Set the emulation type ; SETEMUL LD DE,EMLTAB LD A,CMKEY CALL COMND JP KERMT2 LD (TEMP1),A LD A,CMCFM CALL COMND JP KERMT3 LD A,(TEMP1) LD (EMULFLAG),A JP KERMIT ; ; Set file-warning status ; SETWARN SETFLG FLWFLG ;Set the file-warning flag ; ; SET FILE parse and jump ; SETFILE LD DE,FILETAB ;Get the table of choices LD A,CMKEY ;Select keyword parse CALL COMND ;Parse the input JP KERMT2 ;Abort on an error LD C,A LD B,0 LD HL,FILJTAB ;Get the jump table ADD HL,BC JP (HL) ;Go to the routine ; ; SET FILE jump table ; FILJTAB JP SETDISP ;SET FILE DISPOSITION JP SETTYPE ;SET FILE TYPE JP SETWARN ;SET FILE WARNING ; ; SET FILE TYPE ; SETTYPE LD DE,TYPETAB ;Get the table LD A,CMKEY CALL COMND JP KERMT2 ;Abort on an error LD (TEMP1),A ;Save the value LD A,CMCFM ;Get a confirm CALL COMND JP KERMT3 ;Say not confirmed LD A,(TEMP1) ;Get the value back LD (FILTYPE),A ;Set the type chosen JP KERMIT ;Get another command ; ; Set Printer command ; PRINTR SETFLG PRTFLG ; ; Set status of DEBUG ; SETBUG SETFLG DBFLG ; ; SET EIGHTH-BIT quoting status ; SETEIGHT CALL ONOFF LD (EBQFLG),A JP KERMIT ; ; Get an ON/OFF value in A, with a confirm ; ONOFF LD DE,ONTAB ONOFFA LD A,CMKEY CALL COMND JP KERMT2 LD (TEMP1),A LD A,CMCFM CALL COMND JP KERMT3 LD A,(TEMP1) RET ; ; Set a KEY mapping ; SETKEY LD A,CMNUM ;Get the key number CALL COMND JP KERMT2 ;Abort on error IFZ SETKEY_5 ;Abort if no number LD A,D ;Get the MSB must be zero IFNZ SETKEY_4 LD A,E ;Get the LSB LD (KEYNUM),A ;This is the key number LD A,CMTXT ;Get the text definition LD DE,RMTDATA ;Where to put it LD (SOUPTR),DE ;Set the starting address CALL COMND ;Call the parser JP KERMT3 ;Say not confirmed LD HL,DATA LD (KEYPTR),HL PUSH AF XOR A LD (KEYLEN),A POP AF IFZ SETKEY_3 SETKEY_1 CALL GETFCH ;GET A CHARACTER JR NZ,SETKEY_3 CALL GTREAL ;GET THE ACTUAL IF IT IS SPECIAL JP NZ,KERMIT ;Abort on bad string LD E,A ;PUT IT IN E FOR OUTCHR LD A,(DLYFLG) ;WAS IT A DELAY IFZ SETKEY_2 XOR A LD (DLYFLG),A ;RESET THE FLAG JR SETKEY_1 ;GET A NEW CHARACTER SETKEY_2 LD A,E ;Get the character CALL PUTDKEY ;Put it into the buffer JR SETKEY_1 SETKEY_3 LD HL,DATA LD A,(KEYLEN) LD B,A LD A,(KEYNUM) CALL DEFKEY JP KERMIT SETKEY_4 LD DE,OUTRNG CALL PRTSTR JP KERMIT SETKEY_5 LD DE,KEYHELP CALL PRTSTR SETKEY_6 CALL CONIN IFZ SETKEY_6 LD (KEYNUM),A CALL VERPRT LD DE,STRHELP CALL PRTSTR LD HL,DATA LD B,0 SETKEY_7 CALL CONIN IFZ SETKEY_7 IFA 128,SETKEY_10 LD (HL),A CALL VERPRT INC B LD A,255 IFA B,SETKEY_10 INC HL JR SETKEY_7 SETKEY_10 LD A,B LD (KEYLEN),A JR SETKEY_3 ; ; Put the decoded value into the buffer pointer to by KEYPTR ; PUTDKEY PUSH HL LD HL,(KEYPTR) LD (HL),A INC HL LD (KEYPTR),HL LD HL,KEYLEN INC (HL) POP HL RET ;end of file <<< m4show.asm >>> ; m4show/asm ; ;THIS IS THE SHOW COMMAND. ; SHOW LD A,SHLEN ;GET THE OFFSET TO OVERWRITE WITH LD (SETTAB),A ;FIX SET TABLE FOR SHOW LD (SETTAB+1),A LD A,CMKEY ;Parse a keyword LD DE,SHOTAB ;From this table CALL COMND ;Go do it JP KERMT2 ;Say ambiguous if nothing matches IFA KYLEN,NOCFM ;If keyword is KEY, then special case IFA FILLEN,NOCFM ;If keyword is FILE, then special case LD (TEMP1),A ;SAVE THE JUMP OFFSET LD A,CMCFM ;Get a confirm CALL COMND JP KERMT3 ;SAY NOT CONFIRMED ON AN ERROR CALL NEWLIN ;Get a new line to print on LD A,(TEMP1) ;Get the keyword value NOCFM LD HL,SHOJTB ;Get the start of the jump table LD C,A ;Make BC a 16-bit copy of A LD B,0 ADD HL,BC ;HL IS WHERE WE GO LD BC,KERMIT ;Put a return address on the PUSH BC ;stack to simulate a call JP (HL) ;GO DO THE ROUTINE ; ; Show command jump table. The 2 equates embedded in this table ; indicate functions which need furthur parsing. These are checked ; above, and then handled special. ; SHOJTB JP ESCSTAT ;SHOW ESCAPE JP ECHSTAT ;SHOW LOCAL ECHO JP EIGSTAT ;Eight bit quoting status FILLEN EQU $-SHOJTB JP FILESTAT ;Show the file parameters JP CHKSTAT ;SHOW BLOCK-CHECK-TYPE JP EMULSTAT ;SHOW emulation status JP PRTSTAT ;SHOW PRINTER JP DEBSTAT ;SHOW DEBUGGING JP DSKSTAT ;SHOW DEFAULT DISK JP BELLSTAT ;BELL STATUS JP RCVSTAT ;SHOW RECEIVE JP SENDSTAT ;SHOW SEND KYLEN EQU $-SHOJTB ;THESE 2 LINES MUST BE TOGETHER JP KYSTAT ;SHOW A KEY TRANSLATION JP FLOWSTAT ;SHOW FLOW CONTROL JP SHOINP ;SHOW INPUT PARAMETERS JP SHOOUT ;SHOW OUTPUT PARAMETERS JP TAKESTAT ;SHOW STATUS OF TAKE DISPLAY JP SHOALL ;SHOW ALL ; ; Show the status of several values. This is the STATUS command ; STATUS LD A,CMCFM ;GET A CONFIRM CALL COMND JP KERMT3 ;QUIT ON AN ERROR STROUT SPACSTR LD HL,DEFTABLE+DEFTLEN-1 ;Get the end of table LD BC,(TOPADDR) ;Get the current top OR A ;Reset carry SBC HL,BC ;Compute difference CALL NOUT ;Print the number CALL NEWLIN CALL SHOTRANS JP KERMIT ; ; Show the values of all setable values other than keystrokes. ; There is a lot of code here to perform the 2 column output. ; SHOALL EQU $ STROUT SENDRECV ;Send Receive header FORMAT BELSTR,SHSTRLEN ;Print setting of BELL FOFFON BELFLG FORMAT EOLST,SRSTRLEN ;Print send/recv EOL values LD HL,SEOL CALL SRSTATS FORMAT PNTSTR,SHSTRLEN ;Print status of printer FOFFON PRTFLG FORMAT RETST,SRSTRLEN ;Print send/recv turn around values LD HL,STURN CALL SRSTATS FORMAT BUGST,SHSTRLEN ;Print setting of debug flag FOFFON DBFLG FORMAT PCHST,SRSTRLEN ;Print send/recv padding characters LD HL,SPADCH CALL SRSTATS FORMAT TYPEST,SHSTRLEN ;Print file-type (ASCII or BINARY) LD A,(FILTYPE) LD DE,ASCIIST IFZ SHOA_1 LD DE,BINST SHOA_1 CALL PRTSTR CALL NEWLIN FORMAT QTEST,SRSTRLEN ;Print send/recv eighth bit quotes LD HL,SQUOTE CALL SRSTATS FORMAT LOCST,SHSTRLEN ;Print local echo setting FOFFON ECOFLG FORMAT TOST,SRSTRLEN ;Print send/recv time out values LD HL,STIME CALL SRSTATS FORMAT ESCST,SHSTRLEN ;Print escape character CALL STDOUT CALL ESCPR CALL STDEND CALL NEWLIN FORMAT PADST,SRSTRLEN ;Print send/recv padding amounts LD HL,SPAD CALL SRSTATS FORMAT FILST,SHSTRLEN ;Print file warning setting FOFFON FLWFLG FORMAT SOPST,SRSTRLEN ;Print send/recv SOP characters LD HL,SSOHCH CALL SRSTATS FORMAT FLOWST,SHSTRLEN ;Print flow control setting LD A,(FLOFLG) LD DE,XONSTR IFNZ SHOA_2 LD DE,NONSTR SHOA_2 CALL PRTSTR CALL NEWLIN STROUT INPUTSTR ;Print Input settings message FORMAT DSKDEF,SHSTRLEN ;Print the default disk drive CALL STDOUT LD A,(DEFDSK) CALL CONOUT CALL STDEND CALL NEWLIN FORMAT IDSPST,SRSTRLEN ;Print INPUT DISPLAY setting LD A,(INDSP) CALL JUSONOFF LD BC,0620H ;Display 6 spaces (B is count, C is char) CALL MULDIS CALL DISSEP FORMAT EMSTR,SHSTRLEN ;Print setting for emulation LD A,(EMULFLAG) LD DE,NOESTR IFZ SHOA_3 LD DE,DMESTR SHOA_3 CALL PRTSTR CALL NEWLIN FORMAT CSEST,SRSTRLEN ;Print INPUT CASE-IGNORE setting LD A,(CSEFLG) CALL JUSONOFF LD BC,0620H CALL MULDIS CALL DISSEP FORMAT DISPST,SHSTRLEN ;Print file dispostion CALL STDOUT LD A,(DISCARD) LD DE,DSCRDST IFNZ SHOA_4 LD DE,KEEPST SHOA_4 CALL PRTSTR CALL STDEND CALL NEWLIN STROUT OUTPUTSTR ;Print Output settings message FORMAT BCKST,SHSTRLEN ;Print block check type CALL STDOUT LD A,(CHKTYP) CALL CONOUT STROUT BCKST1 CALL STDEND CALL NEWLIN FORMAT ODSPST,SRSTRLEN ;Print OUTPUT DISPLAY setting LD A,(OTDSP) CALL JUSONOFF LD BC,0620H CALL MULDIS CALL DISSEP FORMAT TAKST,SHSTRLEN ;Print take file display setting FOFFON TAKLOG FORMAT HSTEST,SRSTRLEN ;Print OUTPUT HOST-ECHO setting LD A,(ECHFLG) CALL JUSONOFF LD BC,0620H CALL MULDIS CALL DISSEP FORMAT EIGHTSTR,SHSTRLEN ;Print eight bit quoting status FOFFON EBQFLG CALL NEWLIN JP KERMIT ;Get a new command ; ; Print status of take file display ; TAKESTAT STROUT TAKST SHOFFON TAKLOG ; ; Print status of eighth bit quoting ; EIGSTAT STROUT EIGHTSTR SHOFFON EBQFLG ; ; Print file disposition ; DISPSTAT STROUT DISPST CALL STDOUT LD A,(DISCARD) LD DE,DSCRDST IFNZ DISP_4 LD DE,KEEPST DISP_4 CALL PRTSTR CALL STDEND JP NEWLIN ; ; Show the SET INPUT parameters ; SHOINP CALL NEWLIN ;GET A NEW LINE STROUT CSEST LD A,(CSEFLG) CALL COFFON CALL NEWLIN STROUT IDSPST SHOFFON INDSP ; ; Print the SET OUTPUT parameters ; SHOOUT CALL NEWLIN STROUT HSTEST LD A,(ECHFLG) CALL COFFON CALL NEWLIN STROUT ODSPST LD A,(OTDSP) CALL COFFON JP NEWLIN ; ; Flow control setting ; FLOWSTAT STROUT FLOWST LD DE,XONSTR LD A,(FLOFLG) OR A JP NZ,PRTSTR LD DE,NONSTR JP PRTSTR ; ; Show status of all send parameters ; SENDSTAT LD A,CMCFM CALL COMND JP KERMT3 CALL NEWLIN SHSSTAT EOLST,SEOL SHSSTAT RETST,STURN SHSSTAT PCHST,SPADCH SHSSTAT QTEST,SQUOTE SHSSTAT TOST,STIME SHSSTAT PADST,SPAD SHSSTAT SOPST,SSOHCH RET ; ; Show status of all receive parameters ; RCVSTAT LD A,CMCFM CALL COMND JP KERMT3 CALL NEWLIN SHRSTAT EOLST,REOL SHRSTAT RETST,RTURN SHRSTAT PCHST,RPADCH SHRSTAT QTEST,RQUOTE SHRSTAT TOST,RTIME SHRSTAT PADST,RPAD SHRSTAT SOPST,RSOHCH RET ; ; Show status of bell for KERMIT messages ; BELLSTAT STROUT BELSTR SHOFFON BELFLG ;Print the bell status ; ; Show status of local echo ; ECHSTAT STROUT LOCST ;Local echo is ... SHOFFON ECOFLG ;Print local echo status ; ; Show the type of emulation ; EMULSTAT STROUT EMSTR ;Emulation is ... LD A,(EMULFLAG) OR A LD DE,NOESTR JP Z,PRTSTR LD DE,DMESTR JP PRTSTR ; ; Show file parameters ; FILESTAT LD DE,FILETAB ;Get the options LD A,CMKEY ;Get a keyword CALL COMND ;Parse it JP KERMT2 ;Say ambiguous if error CALL NEWLIN LD (TEMP1),A ;Save the value LD A,CMCFM ;Get a confirm CALL COMND JP KERMT3 ;Say not confirmed if it is not LD A,(TEMP1) ;Get the value back LD C,A ;Put it into BC as 16 bits LD B,0 LD HL,SHFLJTAB ;Get the jump table ADD HL,BC ;Get the destination JP (HL) ;Jump into the table ; SHFLJTAB EQU $ JP DISPSTAT ;SHOW FILE DISPOSITION JP TYPESTAT ;SHOW FILE TYPE JP WARNSTAT ;SHOW FILE WARNING ; ; Show file-type, ASCII or BINARY ; TYPESTAT STROUT TYPEST ;File type is ... LD DE,ASCIIST ;Get ASCII type LD A,(FILTYPE) ;Check the type OR A ;Set the flags JP Z,PRTSTR ;Jump if ASCII LD DE,BINST ;Get binary type JP PRTSTR ;Print the string in rev video ; ; Show the default disk-drive ; DSKSTAT STROUT DSKDEF ;Default disk is ... CALL STDOUT ;REVERSE VIDEO ON LD A,(DEFDSK) ;GET THE CHARACTER 0-9 CALL CONOUT JP STDEND ;REVERSE VIDEO OFF ; ; Show status of file warning ; WARNSTAT STROUT FILST ;File warning is ... SHOFFON FLWFLG ;Show the file warning status ; ; Show status of debug setting ; DEBSTAT STROUT BUGST ;Debugging is ... SHOFFON DBFLG ;Show the debugging ; ; Show status of logging to the printer. ; PRTSTAT STROUT PNTSTR ;Printer is ... SHOFFON PRTFLG ;Show printer status ; ; Show block check type ; CHKSTAT STROUT BCKST ;Block check type is ... CALL STDOUT ;REVERSE VIDEO ON LD A,(CHKTYP) ;GET THE TYPE (CHARACTER 1, 2, OR 3) CALL CONOUT CALL STDEND ;REVERSE VIDEO OFF LD DE,BCKST1 ;GET REST OF TEXT ("-CHARACTER") JP PRTSTR ;. . . ; ; Show the escape character ; ESCSTAT STROUT ESCST ;Escape character is ... CALL STDOUT ;REVERSE VIDEO ON CALL ESCPR ;PRINT THE ESCAPE CHAR. JP STDEND ;REVERSE VIDEO OFF ; ; Pick a character up from (HL+BC) ; GETTRN EQU $ LD C,A ADD HL,BC LD A,(HL) RET ; ; Put a characcter at (HL+BC) ; PUTTRN EQU $ ADD HL,BC LD (HL),A RET ; ; Show the mapping of a keystroke ; KYSTAT LD A,CMNUM ;GET WHICH KEY CALL COMND ;GET IT JP KERMT3 ;SAY NOT CONFIRMED IFZ KYST_4 ;Say ambiguous if no number given LD A,D ;CHECK FOR OVERFLOW IFNZ KYST_3 ;Jump if > 255 CALL NEWLIN LD A,E ;Get the key number KYST_0 EQU $ CALL KEYTRANS ;Do the translation OR H ;Check if there is one JR Z,KYST_2 ;Jump if not CALL NEWLIN ;Print a new line KYST_1 EQU $ LD A,(HL) ;Get a character OR A ;Is it a null RET Z ;Return if end of string CALL VERPRT ;Print verbose description INC HL ;Point to next JR KYST_1 ;Loop until done KYST_2 EQU $ LD DE,NODEF ;Print undefined message JP PRTSTR KYST_3 STROUT OUTRNG ;Print bad value message JP KERMIT KYST_4 STROUT KEYHELP ;Ask them to press a key KYST_5 CALL CONIN ;Get the keystroke IFZ KYST_5 ;If none pressed, then loop PUSH AF ;Save the key CALL VERPRT ;Print it out POP AF ;Restore key JR KYST_0 ;Go process the key ; ; Print verbose string of A. Control characters appear as ; ^M for , etc... ; VERPRT IFAGE ' ',VER_2 ;Jump if character not a control char VER_1 PUSH AF ;Save the character LD A,'^' ;Print a carrat first CALL CONOUT ;Output it POP AF ;Get the character back ADD A,64 ;Uncontrolify it AND 127 ;Remove eighth bit for JP CONOUT ;Output and return VER_2 IFA 127,VER_1 ;If then process as control char JP C,CONOUT ;If less that 127 then print it ; ; Characters greater than 127 are printed as \nnn, where ; nnn is the 3 digit octal number representing the value ; of the character ; LD C,A ;Save the character LD A,'\' ;Get a leading \ CALL CONOUT ;Output it LD A,C ;Get a copy of the character AND 0C0H ;Save only 2 higher order bits RLC A ;Move the 2 bits into the lower RLC A ;order bits of A AND 3 ;Make sure nothing else is there ADD A,'0' ;Make it a printable value CALL CONOUT ;Output it LD A,C ;Get another copy AND 38H ;Save bits 5-3 SRL A ;Align in lower order bits of SRL A ;the accumulator SRL A AND 07H ;Truncate to 3 bits only ADD A,'0' ;Make it printable CALL CONOUT ;Output it LD A,C ;Get the character again AND 07H ;Save lower 3 bits, 2-0 ADD A,'0' ;Make it printable JP CONOUT ;Output it, and return ; ; Right justify the string in DE, within a field as wide as ; HL specifies. ; LEFTPAD PUSH DE ;Save the strings address for printing CALL STRLEN ;Get the length in BC OR A ;Reset the carry SBC HL,BC ;Compute the difference to pad LD B,L ;Make B the count LD A,L ;Check for no padding IFZ LEFTP_2 ;Jump if none needed LEFTP_1 LD A,' ' ;Get the pad character CALL CONOUT ;output one DJNZ LEFTP_1 ;Loop until done LEFTP_2 POP DE ;Restore the strings address JP PRTSTR ;Print it, and return ; ; DISSEP LD DE,SEPAR JP PRTSTR ; ; Display SEND and RECEIVE status as indicated by values at ; the address pointed to be HL, and HL+1. ; SRSTATS EQU $ LD A,(HL) ;Get the value PUSH HL ;Save the address CALL DISNUM ;Display the value LD A,' ' ;Put in an extra blank CALL CONOUT POP HL ;Get the address back INC HL ;Point to receive value LD A,(HL) ;Get the value CALL DISNUM ;Display the value CALL DISSEP ;Put in the separator RET ; ; Display value in A, in a 5 character field ; DISNUM EQU $ LD DE,DECBUF ;Get the buffer LD L,A ;Put the value into HL LD H,0 CALL XHEXDEC ;Convert to printable EX DE,HL ;Put ending address into HL LD (HL),EOS ;Put in a terminator STROUT DECBUF ;Output the string RET ; ; Display the character in C, B times on the screen ; MULDIS PUSH AF ;Save AF, don't destroy it MULDIS1 LD A,C ;Get the character to print CALL CONOUT ;Output one DJNZ MULDIS1 ;Loop until all done POP AF ;Restore AF RET ;Return ; ; Print the ON string, or the OFF string, based on the value in ; A. ; JUSONOFF EQU $ LD DE,OFFSTR ;Get the default before test IFZ JUSON_1 ;Jump if OFF is right LD DE,ONSTR ;Get ON, since A is non-zero JUSON_1 LD HL,7 ;Make the field 7 characters wide JP LEFTPAD ;Go pad it, and return from there ; ; Print ON or OFF based on the status of A. This is different ; from JUSONOFF because here, we do not right justify in a ; fixed length field. ; COFFON LD DE,OFFSTR ;START WITH OFF AS DEFAULT OR A ;SET THE FLAGS JP Z,PRTSTR ;GO PRINT OFF IF A ZERO LD DE,ONSTR JP PRTSTR ; end of file <<< m4str.asm >>> ; M4STR/ASM ;Pure storage. FLINK DS 256 ;FAILURE LINK STORAGE STRING DS 256 ;STORAGE FOR THE STRING TO MATCH LENGTH DB 0 ;LENGTH OF STRING BUFPTR DW 0 ;POINTER INTO THE BUFFER MULBUF DS 256 ;THE BUFFER CTLTBL DB 35 DB 'ACK',6,254,'BEL',7,254,'BS',8,254 DB 'CAN',24,254,'CR',13,254,'DC1',17,254 DB 'DC2',18,254,'DC3',19,254,'DC4',20,254 DLY EQU 250 DB 'DEL',127,254,'DLE',16,254,'DLY*',DLY,254 DB 'EM',25,254,'ENQ',5,254,'EOT',4,254 DB 'ESC',27,254,'ETB',23,254,'ESC',27,254 DB 'FF',12,254,'FS',28,254,'GS',29,254 DB 'HT',9,254,'LF',10,254,'NAK',21,254 DB 'NUL',0,254,'RS',30,254,'SI',15,254 DB 'SO',14,254,'SOH',1,254,'SPA',32,254 DB 'STX',2,254,'SUB',26,254,'SYN',22,254 DB 'VS',31,254,'VT',31,254 DB 0 GTSTRG DS 6 ;String space for storing above ANSI strs WLDBUF DS 6 ;Save wildcards here ALRMAD DW ALARM ;Delay TCB TIMER DW 0 ;Counter RECTIME DW RECTIMOUT ;Receive timeout TCB SVTIMER DW 0 TKNAME DB 'KERMIT/INI',13 ;Name of the initialization file TKLEN EQU $-TKNAME ;Length of the name ; THE FOLLOWING FLAGS ARE STATE FLAGS FOR WHEN EOF OCCURS. ; IF ANY ARE SET WHEN EOF OCCURS THAN AN ERROR HAS OCCURED. INBUF DS 102H ;FILE INPUT BUFFER HSTCHR DB 0 ;TERMINATOR FROM THE HOST IN '*' DLYFLG DB 0 ;WAS A DELAY INVOKED CHRGOT DB 0 ;ACTUAL CHARACTER FROM THE FILE ; PARSING OPTION FLAGS CSEFLG DB 0 ;IGNORE CASE FLAG SPTFLG DB 0 ;ECHOING OF SET OPTIONS IS ON ECHFLG DB 0 ;IS ECHO OF SENT STRINGS ON EXTFLG DB 1 ;EXIT AT EOF FLAG ; EARLY EOF STATE FLAGS ESFLG DB 0 ;ESCAPE CHARACTER SEQUENCE CTLFLG DB 0 ;CONTROL CHARACTER SEQUENCE SNDFLG DB 0 ;SEND STATE FLAG RECFLG DB 0 ;RECEIVE SATE FLAG MULFLG DB 0 ;MULTI-SEND STATE FLAG OPTFLG DB 0 ;SET OPTIONS STATE FLAG BUFFSIZE EQU 2048 ;Size of buffer SRCPTR DW 0 ;Source string pointer HASWILD DB 0 ;Wild cards present flag SPAT DW 0 ;Pattern pointer SSTR DW 0 ;String pointer PSAVE DW 0 ;Saved pattern pointer SSAVE DW 0 ;Saved string pointer SDIRDRV DB '0' ;Saved current drive DIRBUFF DS 256 ;Buffer for DIR/SYS record COMPNAME DS 32 ;Complete file name FNLEN DB 0 ;Length of pattern MOREDRV DB 0 ;More drives to check flag DIRFCB DB 'DIR/SYS:' ;Directory file control block DIRDRV DB '0',CR ;Where to put the drive number DC 23,0 ;Remaining, for 33 bytes total TFBUF DS 256 ;Current pattern storage FILEBUFF DS BUFFSIZE ;Place for file name list FBPTR DW FILEBUFF ;Pointer to next available space FILECNT DB 0 ;Number of file names in FILEBUFF DIRSPEC DB 'DIR/SYS:' ;DIR/SYS pattern DLEN EQU $-DIRSPEC ;Length of text to move PARMS DB 80H ;@PARAM parse table DB 56H DB 'SYSTEM' SYSRESP DB 0 DW SYSFLAG DB 55H DB 'INVIS' INVRESP DB 0 DW INVFLAG DB 0 SYSFLAG DW 0 INVFLAG DW 0 BADCD DB 13,'Bad code inside of <...>',39,'s',EOS NOECHO DB 13,'Host did not echo last character sent',13,EOS QUTMES DB 13,'Ignoring => ',EOS STOBIG DB 13,'String too big for buffer!',13,EOS LGFAIL DB 13,'Operation aborted!',13,EOS PREESC DB 13,'Missing character following \',13,EOS PRECTL DB 13,'Missing character following ^',13,EOS PREOPT DB 13,'Missing > in <...> sequence',13,EOS TXTHLP DB CR,16,'Enter a text string',17,CR,EOS FILHLP DB CR,16,'Enter a file specification!',17,CR,EOS NUMHLP DB CR,16,'Enter a Decimal number!',17,CR,EOS FILESFND DB 'Sending files:',CR,EOS NOFILES DB 16,'No files found',17,CR,EOS OUTOFSTR DB 16,'Too many files, out of space',17,CR,EOS NOTIMER DB CR,16,'No task slots available for timeout',17,CR,EOS NODELAY DB CR,16,'No task slots available for delay, using 1 second' DB 17,CR,EOS NOMEM DB CR,16,'Can',39,'t move LOW$ to new value',17,CR,EOS BADPARM DB CR,'Bad parameter list',CR,EOS TRANABRT DB 'Transaction aborted',CR,EOS TRANCANC DB 'Transaction canceled',CR,EOS WRTPROT DB CR,'Drive is write protected',EOS DSKOK DB CR,'Default drive changed',CR,EOS REMOVSTR DB 'Removing: ',EOS TIMEMES DB ' Time: ',EOS LOGERROR DB 'Log file I/O error. ' ERMS20 DB 'Log file CLOSED!',CR,EOS BLANKS DB ' ',EOS INTRO DB CR,'TRS-80 Model 4(p) TRSDOS 6.2 - KERMIT - Version' DB ' 5.2',CR,'By Gregg Wonderly',CR,CR DB 'Type a ? for help at any time....',CR,EOS CFCL DB CR,'No *CL DCB!',CR,EOS CFSO DB CR,'No *SO DCB!',CR,EOS CFSI DB CR,'No *SI DCB!',CR,EOS NONDCB DB CR,'Can not find a DCB for the *FI or *FO devices!' DB CR,EOS NOSPACE DB CR,'Not enough space left for definition',CR,EOS KPLUS DB 'K + ',EOS BYTESMES DB ' bytes transfered.',EOS KEYHELP DB CR,'Press keystroke you desire: ',EOS STRHELP DB CR,'Enter definition string, end with ' DB '(255 characters MAX)',CR,EOS SPACSTR DB CR,'Remaining key definition space: ',EOS TOOLONG DB CR,'String too long for one packet!',CR,EOS NPKTSTR DB CR,'Number of packets => ',EOS NRTRSTR DB CR,'Number of retries => ',EOS NCHRSTR DB CR,'Bytes transfered => ',EOS NRECCH DB CR,'Kbytes received => ',EOS NSNDCH DB CR,'Kbytes transmitted => ',EOS CBATCH DB 32,16,'[Cancelling batch]',17,32,EOS CFILE DB 32,16,'[Cancelling file]',17,32,EOS UNKNOWN DB CR,'Unknown packet type',CR,EOS HELPMSG DB CR,' CTRL-F => Cancel file ' DB 'CTRL-B => Cancel Batch' DB CR,' CTRL-C => Quit protocol ' DB 'CTRL-A => Transfer status' DB CR,' CTRL-D => Toggle debugging ' DB 'CTRL-H => This message' DB CR,' CTRL-E => Send error, quit ' DB 'ENTER => Resend last packet',CR,EOS RMMES DB BELL,32,16,'[Discarded]',17,32,EOS DO62DR DB 'CAT ' DO61DR DB 'DIR ' DIRCMD DS 4 DIRBUF DS 256 DEFTRLOG DB 'TRANS/LOG',CR DEFSESLOG DB 'SESSION/LOG',CR DEFDEBLOG DB 'DEBUG/LOG',CR DECBUF EQU $ NBUFF DS 6 VISIBLE DB 0 THEVAL DW 0 RMTPTR DW 0 OUTADDR DW 0 PREVCH DB 0 CURLEN DB 0 MAXLEN DB 0 CURCOL DB 0 MAXCOL DB 78 RPTFLG DB 0 NEXT DW 0 RPTCNT DB 0 RPTQ DB '~' EBQFLG DB 1 EBQ DB '&' MYCTLQ DB '#' LEFTOVER DS 7 CH DW 0 DISCARD DB 0 LOGNAMES DB 1 INITRMT DW 0 INITCNT DW 0 PKTTYPE DB 0 FLDLEN DW 0 KTRANS DW 0 RTRANS DW 0,0 STRANS DW 0,0 CURTRANS DW 0,0 SOUPTR DW 0 XOFREC DB 0 TAKLOG DB 0 RECTYP DB 0 SNDTYP DB 0 INDSP DB 0 OTDSP DB 0 PREVLCHR DB 0 ;Previous character logged to session log TRTAB DB 0,1,2,3,4,5,6,7,24,9,26,11,12,29,0,0,16,17,18,19,20 DB 21,22,23,24,25,26,27,28,29,30,31,32,33 KEYTABLE DC 512,0 ;Must be 256 words of zeroes DW 0 ;A little padding for off by one errors TOPADDR DW DEFTABLE DEFTABLE DS 2048 ;Key definition space DEFTLEN EQU $-DEFTABLE KEYPOS DW ATNULL ;Initial buffered string pointer ATNULL DB 0 ;A null byte to signal no characters DIFFADDR DW 0 STRINGLEN DB 0 SAVEDKEY DB 0 KEYSTRING DW 0 KEYNUMBER DB 0 TABLEADDR DW 0 CMPADDR DW 0 MOVEDIFF DW 0 KEYNUM DB 0 KEYPTR DW 0 KEYLEN DB 0 OUTRNG DB CR,'Value out of range!!',CR,EOS NODEF DB CR,'No definition exists',EOS SOUFCB DS 40 TAKFLG DB 0 INCNT DB 0 XFFLG DB 0 FLOFLG DB 1 TFCB DS 32 OLDLOW DW 0 FLAGS DW 0 BEPLEN DB 0 BELFLG DB 1 CLDCB DW 0 TMIDCB DW 0 TMODCB DW 0 RFIDCB DW 0 MAXCNT DB 180 SVMAX DB 80 DISFLG DB 1 HLPMES DB 8,' One of the following...',CR,EOS SORFLG DB 0 MAXTRY DB 7 GENTYPE DB 0 GENLEN DB 0 SORLOC DW 0 LOGOPN DB CR,16,'Logfile is already OPEN!',17,CR,EOS NOLOGF DB CR,16,'Logfile is not OPEN!',17,CR,EOS SNDREC DB EOS KERREC DB 13,'Receiving => ',EOS KERSND DB 13,'Sending => ',EOS DSSOP EQU 1 DRSOP EQU 1 SWTBUF DS 2048 CONCRS DW 0 CMDCRS DW 0 FTIME DB 0 SNDST DB 0 TIME DB 30H TBUF DS 256 ;TAKE COMMAND INPUT BUFFER. ; ; The next 512 bytes produce a 256 byte circular buffer for ; the communications input routine. ; DS 256 CHRBUF DS 256 CURCHR DW CHRBUF ;Buffer is initially empty NXTCHR DW CHRBUF DB 'SETCOM ' CLBUF DS 256 KERM DB 14,16,17,'KERMIT 4(p)>',EOS ;cursor on at prompt CRLF DB CR,EOS ERMES1 DB CR,16,'Unrecognized command',17,CR,EOS ERMES2 DB CR,16,'Illegal character',17,CR,EOS ERMES3 DB CR,16,'Not confirmed',17,CR,EOS ERMES4 DB 'Unable to receive initiate',CR,EOS ERMES5 DB 'Unable to receive file name',CR,EOS ERMES6 DB 'Unable to receive end of file',CR,EOS ERMS10 DB 'Unable to receive data',CR,EOS ERMS17 DB CR ERMS11 DB 'System DOS error',CR,EOS ERMS14 DB 'No acknowledgement from the host',CR,EOS ERMS15 DB CR,'Unable to find file',CR,EOS ERMS16 DB 'Unable to rename file',EOS ERMS18 DB CR,'Unable to tell host that the session is finished',EOS ERMS19 DB CR,'Unable to tell host to logout',EOS INFMS3 DB BELL,CR,'Completed',EOS INFMS4 DB BELL,'Failed',EOS INFMS5 DB 'Renaming file => ',EOS INFMS6 DB CR,'',EOS INFMS7 DB CR,'',CR DB ' is Control-',95,CR,EOS INFMS9 DB CR,'',EOS INMS10 DB 'Control-',EOS INMS13 DB BELL,CR,'Interrupted',EOS INMS18 DB CR,'File KILLED',EOS CFRMES DB CR,16,'Confirm with , cancel with ',17,CR DB EOS CMIN00 EQU CFRMES ABRTMSG DB 'Transfer aborted...' ABRTMSGLEN EQU $-ABRTMSG ESCMES DB CR,'Type the new escape character: ',EOS INTHLP DB 16,CR,17,CR,CR DB ' ? = This message',CR DB ' 0 = (zero) Transmit a NULL',CR DB ' B = Send modem break',CR DB ' C = Close the connection',CR DB ' Q = Quit logging session',CR DB ' R = Resume logging session',CR,CR DB 'Type the escape character again to send it to the host.' DB 16,CR,17,EOS ; SENDRECV DB ' ',16,'Send',17,' ',16 DB 'Receive',17,' | ',EOS INPUTSTR DB 16,'Input settings',17,' ' DB '| ',EOS OUTPUTSTR DB 16,'Output settings',17,' ' DB '| ',EOS SEPAR DB ' | ',EOS ONSTR DB 16,'ON',17,EOS OFFSTR DB 16,'OFF',17,EOS XONSTR DB 16,'XON-XOFF',17,EOS NONSTR DB 16,'NONE',17,EOS NOESTR EQU NONSTR ASCIIST DB 16,'ASCII',17,EOS BINST DB 16,'BINARY',17,EOS DMESTR DB 16,'DUMB',17,EOS DSCRDST DB 16,'DISCARD',17,EOS KEEPST DB 16,'KEEP',17,EOS ; ; ; Miscellaneous SET strings ; BELSTR DB 'Bell: ',EOS PNTSTR DB 'Printer: ',EOS BUGST DB 'Debugging: ',EOS TYPEST DB 'File type: ',EOS LOCST DB 'Local echo: ',EOS ESCST DB 'Escape char: ',EOS FILST DB 'File warning: ',EOS FLOWST DB 'Flow control: ',EOS DSKDEF DB 'Default drive: ',EOS EMSTR DB 'Emulation type: ',EOS DISPST DB 'File disposition: ',EOS BCKST DB 'Block check type: ',EOS TAKST DB 'Display TAKE file: ',EOS EIGHTSTR DB 'Eight bit quoting: ',EOS ; ; This value must be the length of the longest of the ; above strings (except the ending EOS). ; SHSTRLEN EQU $-EIGHTSTR-1 ; ; Send/Recv strings ; EOLST DB 'End-of-line: ',EOS RETST DB 'Turn around: ',EOS PCHST DB 'Pad character: ',EOS QTEST DB 'Control quote: ',EOS TOST DB 'Time out value: ',EOS PADST DB 'Padding Length: ',EOS SOPST DB 'Start-of-packet: ',EOS SRSTRLEN EQU $-SOPST+2 ; ; Input strings (Length must fit within SRSTRLEN) ; IDSPST DB 'Display input: ',EOS CSEST DB 'Ignore case: ',EOS ; ; Output strings (Length must fit within SRSTRLEN) ; ODSPST DB 'Display output: ',EOS HSTEST DB 'Match echo: ',EOS ; BCKST1 DB '-character',EOS RPPOS DB 'RPack=>',EOS SPPOS DB 'SPack=>',EOS CLRTOP DB 1CH,1FH,EOS ;clear screen ; ; COMND tables ; ; Structure of command table ; ; 1) Number of entries. ; 2) Length of longest keyword + 2 ; 3) Each entry is arranged as follows ; a) visibility byte, 1-command is visible, 2-invisible ; b) length of command in bytes. ; c) 'name of command and eos' ; d) offset into command table at KERMTB ; e) offset into command table at KERMTB ; ; ---> Note this command table is in alphabetic order. ; COMTAB DB 30 ;Number of keywords in table DB 9 ;LONGEST KEYWORD + 2 DB 1,3,'BYE',EOS,33,33 DB 0,1,'C',EOS,6,6 DB 1,5,'CLEAR',EOS,63,63 DB 1,5,'CLOSE',EOS,66,66 DB 1,7,'CONNECT',EOS,6,6 DB 1,3,'DIR',EOS,36,36 DB 0,1,'E',EOS,3,3 DB 1,4,'ECHO',EOS,69,69 DB 1,4,'EXIT',EOS,3,3 DB 1,6,'FINISH',EOS,27,27 DB 1,3,'GET',EOS,12,12 DB 1,5,'INPUT',EOS,51,51 DB 1,4,'KILL',EOS,39,39 DB 0,1,'L',EOS,42,42 DB 1,5,'LOCAL',EOS,42,42 DB 1,3,'LOG',EOS,9,9 DB 1,6,'LOGOUT',EOS,30,30 DB 1,6,'OUTPUT',EOS,54,54 DB 1,5,'PAUSE',EOS,57,57 DB 1,5,'PULSE',EOS,60,60 DB 0,1,'R',EOS,12,12 DB 1,7,'RECEIVE',EOS,12,12 DB 1,6,'REMOTE',EOS,0,0 DB 0,1,'S',EOS,15,15 DB 1,4,'SEND',EOS,15,15 DB 1,3,'SET',EOS,18,18 DB 1,6,'SETCOM',EOS,45,45 DB 1,4,'SHOW',EOS,21,21 DB 1,6,'STATUS',EOS,24,24 DB 1,4,'TAKE',EOS,48,48 MXSLEN EQU 19 SHOTAB DB SHLEN/3+1 DB MXSLEN ;LONGEST KEYWORD + 2 DB 1,3,'ALL',EOS ;THE OTHER TWO BYTES WILL BE SUBSTITUTED SETTAB DB SHLEN/3 ;Number of entries in the jump table DB MXSLEN ;LONGEST KEYWORD + 1 DB 1,4,'BELL',EOS,27,27 DB 1,16,'BLOCK-CHECK-TYPE',EOS,12,12 DB 1,9,'DEBUGGING',EOS,21,21 DB 1,12,'DEFAULT-DISK',EOS,24,24 DB 1,17,'EIGHT-BIT-QUOTING',EOS,6,6 DB 1,9,'EMULATION',EOS,15,15 DB 1,6,'ESCAPE',EOS,0,0 DB 1,4,'FILE',EOS,9,9 DB 1,12,'FLOW-CONTROL',EOS,39,39 DB 1,5,'INPUT',EOS,41,41 DB 1,3,'KEY',EOS,36,36 DB 1,10,'LOCAL-ECHO',EOS,3,3 DB 1,6,'OUTPUT',EOS,45,45 DB 1,7,'PRINTER',EOS,18,18 DB 1,7,'RECEIVE',EOS,30,30 DB 1,4,'SEND',EOS,33,33 DB 1,12,'TAKE-DISPLAY',EOS,48,48 ; ; File options ; FILETAB DB 3 DB 13 DB 1,11,'DISPOSITION',EOS,0,0 DB 1,4,'TYPE',EOS,3,3 DB 1,7,'WARNING',EOS,6,6 ; ; File disposition options ; DISPTAB DB 2 DB 9 DB 1,7,'DISCARD',EOS,1,1 DB 1,4,'KEEP',EOS,0,0 ; ; Remote commands parse table ; RMTTAB DB 21 DB 16 DB 1,9,'CLOSE-LOG',EOS,42,42 DB 1,4,'COPY',EOS,30,30 DB 1,3,'CWD',EOS,0,0 DB 1,6,'DELETE',EOS,3,3 DB 1,3,'DIR',EOS,6,6 DB 1,4,'DISK',EOS,9,9 DB 1,4,'HELP',EOS,12,12 DB 1,4,'HOST',EOS,15,15 DB 1,6,'KERMIT',EOS,18,18 DB 1,5,'LOGIN',EOS,54,54 DB 1,7,'MESSAGE',EOS,33,33 DB 1,7,'PROGRAM',EOS,57,57 DB 1,14,'QUERY-VARIABLE',EOS,39,39 DB 1,6,'RENAME',EOS,24,24 DB 1,8,'SEND-LOG',EOS,45,45 DB 1,13,'SERVER-STATUS',EOS,60,60 DB 1,12,'SET-VARIABLE',EOS,36,36 DB 1,9,'START-LOG',EOS,48,48 DB 1,8,'STOP-LOG',EOS,51,51 DB 1,4,'TYPE',EOS,27,27 DB 1,3,'WHO',EOS,21,21 ; ; Emulation type parse table ; EMLTAB DB 2 DB 6 DB 1,4,'DUMB',EOS,3,3 DB 1,4,'NONE',EOS,0,0 ; ; Close options parse table ; CLSTAB DB 3 DB 13 DB 1,5,'DEBUG',EOS,1,1 DB 1,7,'SESSION',EOS,0,0 DB 1,11,'TRANSACTION',EOS,2,2 ; ; Clear command options parse table ; CLRTAB DB 2 DB 12 DB 1,10,'INPUT-PORT',EOS,0,0 DB 1,6,'SCREEN',EOS,3,3 ; ; Flow control options parse table ; FLOTAB DB 2 DB 10 DB 1,4,'NONE',EOS,0,0 DB 1,8,'XON-XOFF',EOS,1,1 ; ; SET SEND/RECEIVE options parse table ; STSNTB DB 7 DB 17 DB 1,11,'END-OF-LINE',EOS,12,12 DB 1,8,'PAD-CHAR',EOS,0,0 DB 1,7,'PADDING',EOS,3,3 DB 1,15,'QUOTE-CHARACTER',EOS,15,15 DB 1,15,'START-OF-PACKET',EOS,6,6 DB 1,8,'TIME-OUT',EOS,9,9 DB 1,9,'TURN-CHAR',EOS,18,18 ; ; SET OUTPUT options parse table ; OUTTAB DB 2 DB 11 DB 1,9,'HOST-ECHO',EOS,0,0 DB 1,7,'DISPLAY',EOS,3,3 ; ; SET INPUT options parse table ; INPTAB DB 2 DB 13 DB 1,11,'CASE-IGNORE',EOS,0,0 DB 1,7,'DISPLAY',EOS,3,3 ; ; SET FILE TYPE options parse table ; TYPETAB DB 2 DB 8 DB 1,6,'BINARY',EOS,1,1 DB 1,5,'ASCII',EOS,0,0 ; ; SET BLOCK-CHECK-TYPE options parse table ; BLKTAB DB 3 DB 8 DB 1,1,'1',EOS,'11' DB 1,1,'2',EOS,'22' DB 1,1,'3',EOS,'33' ; ; OFF/ON parse table ; ONTAB DB 4 ;Number of entries DB 5 ;Max length + 2 DB 0,2,'NO',EOS,0,0 ;YES and NO are invisible DB 1,2,'ON',EOS,1,1 DB 1,3,'OFF',EOS,0,0 DB 0,3,'YES',EOS,1,1 ; ; Assorted error/informational messages ; CMER00 DB CR,'Program error, Invalid COMND call',EOS CMER01 DB CR,'Ambiguous',EOS CMER02 DB CR,'Illegal input filespec',EOS CMCRLF DB CR,EOS ; ; Storage for the parser, etc. ; CMSTAT DB 0 ;What is presently being parsed. CMAFLG DB 0 ;Non-zero when an action char has been found. CMCCNT DB 0 ;Non-zero if a significant char is found. CMSFLG DB 0 ;Non-zero when the last char was a space. CMOSTP DW 0 ;Old stack pointer for reparse. CMRPRS DW 0 ;Address to go to on reparse. CMPRMP DW 0 ;Address of prompt. CMPTAB DW 0 ;Address of present keyword table. CMDBUF DS 100H ;Buffer for command parsing. CMFCB DW 0 ;Pointer to FCB. CMCPTR DW 0 ;Pointer for next char input. CMDPTR DW 0 ;Pointer into the command buffer. CMKPTR DW 0 ;Pointer to keyword. CMSPTR DW 0 ;Place to save a pointer. OLDSP DW 0 ;Room for old system stack. DS 200H ;Room for lots of calls STACK DW 0 EOFLAG DB 0 ;EOF flag; non-zero on EOF. FILFLG DB 0 ;NON-ZERO WHEN FILE NOT OPEN LSTCHR DB 0 ;Last character in disk i/o DEFDSK DB '0' ;Default disk drive number LOGFLG DB 0 ;Flag for session logging DEBLOG DB 0 ;Flag for debug logging TRANLOG DB 0 ;Flag for transaction logging ECOFLG DB 0 ;Local echo flag (default off). ESCFLG DB 0 ;Escape flag (start off). EMULFLAG DB 0 ;Emulation flag, NONE is default FLWFLG DB 0 ;file warning flag (default on) FILTYPE DB 0 ;File type, default is ASCII DBFLG DB 0 ;debugging flag (default off) PRTFLG DB 0 ;printer flag (default off) ESCCHR DB DEFESC ;Storage for the escape character. CHRCNT DB 0 ;Number of chars in the file buffer. FILCNT DB 0 ;Number of chars left to fill. OUTPNT DW 0 ;Position in packet. BUFPNT DW 0 ;Position in file buffer. FCBPTR DW 0 ;Position in FCB. FCBEXT DW 0 DATPTR DW 0 ;Position in packet data buffer. LOGPTR DW LBUFF ;pointer into log file buffer CBFPTR DW 0 ;Position in character buffer. PKTPTR DW 0 ;Poistion in receive packet. OSIZE DB 0 ;Old size of packet before overflow SIZE DB 0 ;Size of data from gtchr. SPSIZ DB DSPSIZ ;Send packet size. RPSIZ DB DRPSIZ ;Receive packet size. STIME DB DSTIME ;Send time out. RTIME DB DRTIME ;Receive time out. SPAD DB DSPAD ;Send padding. RPAD DB DRPAD ;Receive padding. SPADCH DB DSPADC ;Send padding char. RPADCH DB DRPADC ;Receive padding char. SEOL DB DSEOL ;Send EOL char. REOL DB DREOL ;Receive EOL char. SSOHCH DB DSSOP ;SEND START OF PACKET RSOHCH DB DRSOP ;RECEIVE START OF PACKET SQUOTE DB DSQUOT ;Send quote char. RQUOTE DB DRQUOT ;Receive quote char. STURN DB 0 ;Send turn around character RTURN DB 0 ;Receive turn around character CHKTYP DB DSCHKT ;Checksum type desired CURCHK DB DSCHKT ;Current checksum type INICHK DB DSCHKT ;Agreed upon checksum type CZSEEN DB 0 ;Flag that control-Z was typed MFNPTR DW MFNBUF ;multiple file processing buffer PKTNUM DB 0 ;Packet number. NUMPKT DW 0 ;Total number of packets sent. NUMRTR DW 0 ;Total number of retries. NUMTRY DB 0 ;Number of tries on this packet. OLDTRY DB 0 ;Number of tries on previous packet. TFILNAM DS 33 ;Space for saved file name printed during GETs RMTDATA DS 101H ;Data for remote commands STATE DB 0 ;Present state of the automaton. PACKET DS 4 ;Packet (data is part of it). DATA DS 101H ;Data and checksum field of packet. RECPKT DS 70H ;Receive packet storage (use the following). FILBUF DS 70H ;Character buffer. ; ;** Temp 1 & 2 must be in order ; TEMP1 DB 0 ;Temporary storage. TEMP2 DB 0 TEMP3 DB 0 TEMP4 DB 0 ; ; Data storage for MFNAME (multi-file access) ; MFREQ DS 40 ;Requested name MFNBUF DS 100H ;filename buffer ; FCB DS 40 ;file control block LFCB DS 40 ;log file fcb TRFCB DS 40 ;Transaction file fcb DFCB DS 40 ;Debug fcb KFCB DS 40 ;kill file fcb BUFF DS 256 ;file buffer LBUFF DS 256 ;log file buffer TBUFF DS 256 ;Transaction log buffer DBUFF DS 256 ;Debug log buffer ARGBLK DS 20H ;Used ; end of file <<< m4term.asm >>> ; m4term/asm ; ; This is the connect command ; CONNECT EQU $ LD A,CMCFM ;Get a confirmation CALL COMND JP KERMT3 ;Abort if no pressed CALL SCRCON ;Swap in the proper screen LD A,(MAXCNT) ;Select the proper buffer size LD (SVMAX),A LD A,80 ;80 characters max are buffered LD (MAXCNT),A LD A,(FTIME) ;Is this the VERY FIRST connect? IFNZ CON_2 STROUT CLRTOP ;Clear the screen CON_1 STROUT INFMS7 ;Display the message CALL ESCPR STROUT INFMS8 LD A,1 ;Set the first time done flag LD (FTIME),A CON_2 LD A,14 CALL CONOUT ; ; While in connect mode, at most, 30 characters may be processed ; from the input port, before the keyboard is scaned. We try not ; to scan the keyboard too much, as that will kill screen I/O. This ; is especially true at higher baud rates, where the user might ; not get to type a key because the flow of characters into the ; port is continuous. ; CHRLUP LD A,30 ;Set the maximum character count LD (CHCNT),A ;Save it CALL PRTCHR ;Do input characters CALL CONCHR ;Get a keyboard character JP KERMIT ;IF we return here, then abort JR CHRLUP ;Loop on ; ; Look at the input buffer for a character, and return it, or ; return no input. ; INPORT PUSH HL ;SAVE HL LD HL,(NXTCHR) ;Get address of next input char LD A,(CURCHR) ;Get the LSB of the queue start IFA L,INOUT ;If A=L, then there is no input. DI ;Interrupts off, CRITICAL section LD A,(HL) ;Get the character back LD (SVCHAR),A ;Save the input character INC L ;Delete the character LD (NXTCHR),HL ;Set the new pointer LD HL,INCNT ;Decrement the count DEC (HL) EI ;Interrupts back on LD A,(FLOFLG) ;Is XON/XOFF in effect? IFZ INP11 ;Go if not doing flow control PUSH BC ;Save BC LD C,(HL) ;Get a copy of the count LD A,(XFFLG) ;Check if XOFF sent out IFZ INP10 ;Jump if not LD A,(MAXCNT) ;It was, so check if time for XON SRL A ;Use 1/2 of the max as the restart count IFALT C,INP10 ;If A >= count it is not time yet PUSH DE ;Save DE LD E,XON ;Get an XON character CALL OUTCHR ;Out the port it goes XOR A ;Reset the XOFF sent flag LD (XFFLG),A POP DE ;Restore E INP10 POP BC ;Restore C INP11 LD A,0 ;Get the next character SVCHAR EQU $-1 CP A ;Set Z status for normal return INOUT1 POP HL ;Restore HL RET ;Back to caller ; ; No input exit from INPORT ; INOUT EQU $ XOR A ;Reset the count LD (INCNT),A ;Zeroed INC A ;Set NZ (We know A was zero, now it is 1) POP HL ;Restore HL RET ;Back to the caller ; ; Input a character, and display it based on the current value ; of EMULATION. ; PRTCHR CALL INPORT ;Try to get an input character. RET NZ ;Return if none there LD E,A ;Get the input character CALL LOGONE ;Maybe do logging LD A,(PRTFLG) ;CHECK FOR PRINTER OUTPUT OR A ;SET THE FLAGS CALL NZ,PRTIT ;GO PRINT IT LD A,E ;GET THE CHARACTER AND DISPLAY CALL TRMOUT ;Send it to the *SO device LD B,0 ;Get the current count CHCNT EQU $-1 DJNZ PRTCHR5 ;SKIP RETURN IF NOT LIMIT RET ;RETURN AFTER LIMIT IS UP PRTCHR5 LD A,B ;GET THE NEW COUNT LD (CHCNT),A ;SAVE IT JP PRTCHR ;LOOP ON ; ; Input a character from the keyboard. ; CONCHR CALL GETKEY ;Get a keyboard character without JP NZ,RSKP ;Return if not one LD E,A ;Is it CONNECT escape character? LD A,(ESCCHR) CP E JP Z,INTCHR ;Go process the next key pressed CONCHR2 IFANOT 128,CONCHR3 ;BREAK? CALL DOBRK ;Generate real BREAK JP RSKP CONCHR3 LD A,E CONCHR4 PUSH DE ;SAVE DE CALL PRTOUT ;SEND IT TO THE PORT POP DE LD A,(ECOFLG) ;CHECK FOR LOCAL ECHO OR A LD A,E CALL NZ,TRMOUT ;Echo out terminal device JP RSKP ;RETURN TO THE CALLER SAY OK ; ; This is the code to process the escape sequences during the ; CONNECT command that do things like return to the KERMIT ; prompt, send a break, turn logging on and off, etc... ; INTCHR EQU $ CALL GETKEY ;Get a character from translator JR NZ,INTCHR ;Loop until we get one INCH00 EQU $ LD B,A ;Put the real character into B AND 137O ;Convert A to upper case IFANOT 'C',INCH01 ;Is it connect, if not try other CALL SCRCMD ;Swap KERMIT screen in LD A,(SVMAX) ;Restore the old max LD (MAXCNT),A RET ;Return to KERMIT INCH01 LD A,B ;Get the real value IFANOT '?',INTCH1 ;Is it help, if not try next LD A,15 ;Turn the cursor off CALL CONOUT LD B,4 ;Get the cursor position CALL XVDCTL PUSH HL ;Save it LD HL,2600H ;Save the screen LD B,6 ;Get screen function CALL XVDCTL ;Do the move LD HL,0C00H ;Move to middle CALL TOSCRPOS ;Move to possition on screen LD A,31 ;Clear to eos CALL CONOUT LD DE,INTHLP ;Get Help message CALL PRTSTR ;Print message INCH11 CALL GETKEY ;Get a character JR NZ,INCH11 ;Jump if no key pressed POP HL ;Reorder the stack PUSH AF PUSH HL LD HL,2600H ;Get the old screen LD B,5 ;Put it back into view CALL XVDCTL POP HL ;Restore old cursor position CALL TOSCRPOS ;Position the cursor LD A,14 ;Turn the cursor back on CALL CONOUT POP AF ;Get the character typed back JR INCH00 ;Loop back to process character ; INTCH1 AND 137O ;Convert back to uppercase IFANOT 'B',INTCH2 ;Is it BREAK, if not try next CALL DOBRK ;Send BREAK out port JP RSKP ;Return NO error INTCH2 LD A,B ;Get the real character IFANOT '0',INTCH3 ;Is it NULL, if not try next LD E,0 ;Get a NULL CALL OUTCHR ;Out the port with it JP RSKP ;Return no error INTCH3 LD E,B ;Get the real character LD A,(ESCCHR) ;Get the escape character IFA E,INTCHZ ;Is it the escape character ? LD A,B ;Get the real character AND 137O ;Upper case again IFANOT 'Q',INTCH4 ;Is it QUIT, if not try next LD A,(LOGFLG) ;Get the logging flag IFANOT 2,INTC3A ;Is logging active, jump if not DEC A ;Turn logging off LD (LOGFLG),A ;Set the value JP RSKP ;Return no error INTC3A LD A,BELL ;Get An error sound CALL CONOUT ;BEEP AT THEM JP RSKP ;Return no error INTCH4 IFANOT 'R',INTCH5 ;Resume logging? Jump if not LD A,(LOGFLG) ;Check logging status IFANOT 1,INTC3A ;If not 1, can't resume INC A ;Turn logging on LD (LOGFLG),A ;Set the value JP RSKP ;Return no error INTCH5 LD A,E ;Get the character typed CALL PRTOUT ;Send it out the port JP RSKP ;Return no error INTCHZ CALL OUTCHR ;Send it out the port LD A,BELL ;Get a bell CALL CONOUT ;Send bell to terminal JP RSKP ;Return no error ; ; Send character to printer ; PRTIT EQU $ LD A,E ;Get the character PUSH DE ;Save E for return CALL XPRT ;Dos printer routine POP DE ;Restore E RET ;Return ; ; Generate a real modem break ; DOBRK LD C,1 ;OPTION 1 OF @CTL LD DE,(CLDCB) ;Get the *CL DCB CALL XCTL ;Do @CTL to start Modem break DI ;Make the pause be exact LD BC,39000 ;Pause for 200ms BRKLOOP DEC BC ;Decrement the count LD A,B OR C JR NZ,BRKLOOP ;Loop until done EI LD E,0 ;Stop break with any character JP OUTCHR ;Null is good ; ; Output any none null character to the RS232 port ; PRTOUT OR A ;Don't send NULLS RET Z LD E,A ;Get the character JP OUTCHR ;Output it ; ; Log a character to the log file ; LOGONE PUSH AF PUSH DE LD E,A LD A,(LOGFLG) OR A LD A,E CALL NZ,LOGIT POP DE POP AF RET ; ; Output a character to *DO ; CONOUT PUSH DE ;SAVE THE REGS PUSH BC PUSH AF IFA BELL,BEEPON ;Go if bell CALL XDSP ;Use the @DSP SVC to display it CON010 POP BC ;Use BC to get A, and not destroy flags LD A,B ;Get the old A POP BC POP DE RET ;RETURN TO THE CALLER ; ; Output a character to *SO ; TRMOUT PUSH DE ;Save the regs PUSH BC PUSH AF LD E,A ;Make a copy of the character LD A,(EMULFLAG) ;Get the emulation flag IFZ TRMOUT3 ;Jump if EMULATION set to NONE ; ; Certain control characters are translated on input. In ; particular, the following mappings are in effect. ; ; 8 -> 24 non destructive backspace ; 10 -> 26 non destructive linefeed ; 13 -> 29 True carriage return ; LD A,E ;Is this a control character? IFAGE 32,TRMOUT3 ;Jump if not a control character LD HL,TRTAB ;Get the translation table LD B,0 ;Make BC an offset into TRTAB ; ; If the character in the translation table is 0, then it is ; ignored. This is handy for blocking out things like cursor ; on/off, and inverse video on/off ; LD C,A ;Get the character to use as index ADD HL,BC ;Index to the table LD A,(HL) ;Get the translated character IFZ TRMOUT5 ;Return if character is to be ignored LD E,A ;Make a copy for later IFANOT 12,TRMOUT1 ;Jump if not a formfeed CALL CMBLNK ;Clear the screen JR TRMOUT5 TRMOUT1 IFANOT 7,TRMOUT3 ;Jump if not bell CALL CONOUT ;DUMB uses BUILTIN Bell JR TRMOUT5 TRMOUT3 EQU $ LD A,E ;Get the character LD DE,(TMODCB) ;Get the Device DCB for terminal out CALL XPUT ;@PUT the character to the device TRMOUT5 POP BC ;Use BC to get A, and leave Flags alone LD A,B ;Get A POP BC ;Restore BC POP DE ;And the rest RET ; ; Input a character from *SI ; TRMIN PUSH DE PUSH BC LD DE,(TMIDCB) ;Get the terminal input DCB CALL XGET ;@GET a character POP BC ;Restore the regs POP DE RET ; ; Sound a bell ; BEEPON LD A,(BELFLG) ;IS THAT OPTION ON? IFZ CON010 ;Jump if bell option off PUSH BC ;Save counter LD C,50 ;Get the duration BEEP1 LD A,1 ;Get the value to send out port OUT (90H),A ;Toggle port high LD B,130 ;Delay DJNZ $ DEC A ;Set A to zero OUT (90H),A ;Toggle port low LD B,130 ;Delay DJNZ $ DEC C ;Decrement duration JR NZ,BEEP1 ;Loop if not done POP BC ;Restore counter JR CON010 ;Join return code ; ; Print string pointed to by DE to *DO, EOS is end of string ; NUL characters are thrown out. ; PRTSTR LD A,(DE) ;GET A CHARACTER CP EOS ;IS IT THE END? RET Z ;RETURN TO CALLER IF SO OR A ;THROW AWAY THE NULL CHARACTER CALL NZ,CONOUT ;DISPLAY ANYTHING NON-NULL INC DE ;POINT TO THE NEXT ONE JR PRTSTR ;LOOP ON ; ; Get a character from *KI ; CONIN PUSH DE ;SAVE DE CALL XKBD ;LOOK AT THE KEYBOARD WITHOUT WAITING POP DE ;RESTORE DE RET ;RETURN TO THE CALLER ; ; Output a character to *CL. The character is in E. ; OUTCHR PUSH DE ;SAVE CURRENT DE AND BC PUSH BC LD C,E ;Put the character where it should be OUTCH0 LD A,(XOFREC) ;CHECK TO SEE IF WE CAN TRANSMIT YET! IFZ OUTCH2 ; ; We allow break to force the transmittion of the character that ; is being sent. There are ways that the XON from the host can ; be lost. This allows control to be regained, without rebooting ; which would be the only other choice. ; OUTCH1 CALL CONIN ;Check the break key IFANOT 128,OUTCH0 ;Jump if not XOR A ;Reset the XOF'd flag LD (XOFREC),A OUTCH2 LD A,C ;Get the character to send OUTCH3 LD DE,(CLDCB) ;GET THE DCB OF THE DEVICE TO PUT TO CALL XPUT ;SEND THE CHARACTER JR NZ,OUTCH3 ;Transmitter may not be ready, loop if ; needed until character is transmitted OUTCH4 POP BC ;Restore the regs POP DE RET ; ; Character input routine for INPKT. We can timeout on the ; receive by allowing the timer to place a return in the code ; below, at the address RECALRM. Since TRSDOS doesn't allow ; us (neatly, without a hack) to transfer control in a task, ; to some other code, we use the self modifying code. This ; may be considered dirty, but it does work. The RET causes ; the code to behave as though the user had pressed to ; resend the latest packet. ; INCHR XOR A ;Get a NOP instruction LD (RECALRM),A ;Remove any stored RET instruction INCHR1 CALL CONIN ;Check keyboard first to make sure IFNZ INCHR3 CALL INPORT ;Get a character from the buffer JP Z,RSKP ;Return if we got one RECALRM NOP ;Modified by timeout code to be a RET JR INCHR INCHR3 IFANOT CR,INCHR4 ;Check which key was pressed LD A,(TASKSLOT) ;Get the active task OR A ;See if task aqctive RET Z ;Return if not LD C,A ;Get the task slot into c CALL XRMTSK ;Stop the task RET ;Return resend status INCHR4 CHKWKEY 'B'-64 ;Control-B for batch CHKWKEY 'F'-64 ;Control-F for file CHKWKEY 'A'-64 ;Control-A for status CHKWKEY 'E'-64 ;Control-E for send error CHKWKEY 'D'-64 ;Debug? CHKWKEY 'H'-64 ;Help? IFANOT 'C'-64,INCHR1 ;Control-C for abort completely INCHR5 ADD A,40H ;MAKE IT PRINTABLE LD (CZSEEN),A RET ; ; Timer task for receiving a packet. Called every 33.333333333 ; milliseconds. We decrement the TIMER counter, and when it ; goes to zero, we write a RET into the above code, and kill ; the task so that is does not return. ; ; Note that we must NOT leave anything on the stack when @KLTSK ; is called or else it will puke. ; RECTIMOUT EQU $ PUSH HL ;Save the registers used PUSH AF LD HL,(TIMER) ;Get the counter DEC HL ;Decrement it LD (TIMER),HL ;Store the new value LD A,H ;Check it for zero OR L JR NZ,RECT1 LD A,0C9H ;Get a RET instruction opcode LD (RECALRM),A ;Write it in POP AF ;Restore the register POP HL JP XKLTSK ;Remove this task, NO RETURN. ; RECT1 POP AF ;Restore the registers POP HL RET ;Return ; ; Move cursor to position on screen ; TOSCRPOS EQU $ LD B,3 JP XVDCTL ;end of file <<< m4wild.asm >>> ; m4wild/asm ; ; Build a list of filenames given a list of arbitrary names ; pointed to by HL. Wild card processing is done here. ; ; The resulting blank separated list is returned in HL. The ; number of names put into the buffer is indicated by the ; count in FILECNT. This is a byte valued count, so 255 is ; the maximum number possible. ; BUILDF EQU $ LD (SRCPTR),HL ;Save the source input pointer LD HL,FILEBUFF ;Set the pointer to the matches LD (FBPTR),HL ;buffer where all matches go XOR A ;Set number of files found to 0 LD (FILECNT),A BF_0 EQU $ LD HL,(SRCPTR) ;Get the input string LD BC,0 ;Get zero LD (SYSFLAG),BC ;No system files LD (INVFLAG),BC ;No invisible files XOR A ;Reset response values LD (INVRESP),A LD (SYSRESP),A LD A,' ' BF_A IFANOT (HL),BF_B INC HL JR BF_A ; BF_B LD DE,PARMS ;Get the parse table CALL XPARAM ;Do @PARAM SVC JR Z,BF_D ;Jump if parse ok BF_C STROUT BADPARM ;Print error message JP KERMIT ;Abort! ; BF_D LD A,(SYSRESP) ;Get the system response AND 0A0H ;Valid? JR NZ,BF_C ;Jump if not LD A,(INVRESP) ;Check invisble flag AND 0A0H ;Valid? JR NZ,BF_C ;Jump if not LD A,' ' ;Get a space to compare with BF_E IFANOT (HL),BF_F ;Jump if not space INC HL JR BF_E ; BF_F LD B,32 ;Move 32 characters, MAX LD DE,TFBUF ;Get the temporary buffer BF_1 LD A,(HL) ;Get a character IFALT ' '+1,BF_2 ;Jump if at end of this filename CALL CPTAL ;Capitalize it LD (DE),A ;Save the new character INC DE ;Increment the pointers INC HL DJNZ BF_1 ;Loop until done BF_2 XOR A ;Terminate the string with a zero LD (DE),A ;Put in a terminator BF_3 LD A,(HL) ;Get the next character IFAGE ' '+1,BF_4 ;Jump if not separator IFA CR,BF_4 ;Jump if end of string INC HL ;Skip the separator JR BF_3 ;Loop on ; BF_4 LD (SRCPTR),HL ;Save the next string pointer LD A,32 ;Get the max length SUB B ;Compute length LD (FNLEN),A ;Save it JP Z,BF_18 ;Exit if no more names LD A,1 ;Initially check all drives LD (MOREDRV),A ;Set the flag DEC DE ;Check if '/' last character EX DE,HL ;Put it in HL LD A,(HL) ;Get the character IFANOT '/',BF_5 ;Is it a '/' LD (HL),0 ;Remove the trailing slash BF_5 LD HL,TFBUF ;Look for a drive specification LD A,(FNLEN) ;Get the length LD C,A ;Make BC a 16 bit copy of A LD B,0 ADD HL,BC ;Compute end of name plus one DEC HL ;Backup to possible drive number DEC C ;Decrement the counter JR Z,BF_7 ;Jump if no characters left DEC HL ;Backup to possible ':' separator DEC C ;Decrement counter JR Z,BF_7 ;Jump no characters left LD A,(HL) ;Get a possible ':' IFANOT ':',BF_7 ;Jump if not drive spec LD (HL),0 ;Terminate with no drive number INC HL ;Point back at drive number LD A,(HL) ;Get the drive number LD HL,FNLEN ;Change the length DEC (HL) DEC (HL) SUB '0' ;Make the drive number binary LD C,A ;Save the drive to check XOR A LD (MOREDRV),A ;No more drives to check JR BF_8 ; BF_7 EQU $ XOR A ;Zero A LD C,A ;Set drive number to zero BF_8 EQU $ PUSH BC ;Save the current drive number CALL XCHKDRV ;Check this drive JP NZ,BF_17 ;Jump if drive not ready LD HL,DIRSPEC ;Get the source of 'DIR/SYS' LD DE,DIRFCB ;Put it here LD BC,DLEN ;Move this many characters LDIR ;Copy the name POP BC ;Get the drive number PUSH BC ;Put it back LD A,C ;Put it into A ADD A,'0' ;Make it printable LD (DIRDRV),A ;Set the drive number LD (SDIRDRV),A ;Save the current drive LD A,CR ;Get a EOL marker LD (DIRDRV+1),A ;Put in a terminator LD HL,DIRBUFF ;Get the buffer LD B,0 ;LRECL = 256 LD DE,DIRFCB ;Get the FCB CALL XOPEN ;Try to open the directory JP NZ,BF_19 ;Jump on open error LD DE,DIRFCB ;Get the FCB CALL XSKIP ;Skip HIT and GAT CALL XSKIP BF_9 EQU $ LD HL,DIRBUFF ;Get the data buffer LD DE,DIRFCB ;Get the FCB CALL XREAD ;Read a record JP NZ,BF_15 ;Jump if can't read anymore LD B,8 ;Number of dir entries LD HL,DIRBUFF ;Get the starting data BF_10 PUSH BC ;Save the counter BIT 4,(HL) ;Check for used directory record JR Z,BF_12 ;Jump entry not in use BIT 7,(HL) ;Check if FPDE JR NZ,BF_12 ;Jump if extent or other LD A,(SYSFLAG) ;Check is system file valid IFNZ BF_10A ;Jump if system OK BIT 6,(HL) ;Is it a system file JR NZ,BF_12 ;Skip it if it is BF_10A LD A,(INVFLAG) ;Is invisible file valid? IFNZ BF_10B ;Jump if invisble ok (no check) BIT 3,(HL) ;Is the file invisible? JR NZ,BF_12 ;Skip it if it is BF_10B LD DE,TFBUF ;Get the pattern to match LD A,1 LD (HASWILD),A ;Set wild cards present flag CALL ISWILD ;Check if it really is JR Z,BF_11 ;Jump if there are wild cards XOR A LD (HASWILD),A ;Reset has wild cards flag BF_11 EQU $ CALL MATCH ;See if it matches JR NZ,BF_12 CALL COPYFILE ;Copy it if it matches LD A,(HASWILD) ;Check if should check others IFNZ BF_12 ;Jump if wild, might be more POP BC ;Otherwise, no wild, so keep only POP BC ;the first match as in TRSDOS's JP BF_0 ;normal drive search algorithm ; BF_12 LD BC,32 ;Get the length of a DIR record ADD HL,BC ;Point to next POP BC ;Restore the number of entries DJNZ BF_10 ;Decrement and loop if not end JR BF_9 ;Try next drive ; ; Control comes to here on an error in the call to @READ. Check ; to make sure it is EOF, and print an error message if not. ; BF_15 EQU $ CP 28 ;Check for end of file JR Z,BF_16 ;Jump if end of file CALL XERROR0 ;Print the error message LD DE,DIRFCB ;Close the open file CALL XCLOSE JP KERMIT ;Abort completely ; BF_16 EQU $ LD DE,DIRFCB ;Close the directory CALL XCLOSE ;Closed JP NZ,BFCLSERR ;Jump if close error BF_17 EQU $ POP BC ;Restore drive number INC C ;Next drive LD A,8 ;Get max drive number (plus 1) CP C ;Get next name if no more drvs JP Z,BF_0 ;Go get next name if end LD A,(MOREDRV) ;See if should check other drvs OR A ;Check for zero JP NZ,BF_8 ;If set, then no drive spec so go JP BF_0 ;Get the next filename in list ; ; At the end of processing, we update the end of the list of names, ; and return the pointer to the start of the list in HL. ; BF_18 EQU $ LD HL,(FBPTR) ;Get the pointer LD (HL),CR ;Terminate the string LD HL,FILEBUFF ;Return the start of the list RET ; ; Control comes to here on a directory open error. Print the error ; message, and then go check next drive. ; BF_19 EQU $ CALL XERROR0 JR BF_17 ; ; Control comes to here if CLOSE on DIR/SYS fails. ; BFCLSERR EQU $ CALL XERROR0 ;Print the error message JP KERMIT ;Return to command level ; ; Do a wild card match on the 2 strings pointed to by ; HL, and DE. DE points at the pattern containing possible ; wild card characters. HL points at the start of a TRSDOS ; complete directory record. HL must be moved to the start ; of the filename. The filename HL points to has up to 11 ; characters in it. The first 8 are the filename, the last ; 3 are the extension. Both are left justified within their ; respective fields, with blanks as fill. ; MATCH EQU $ PUSH BC ;Save BC PUSH HL ;Save HL PUSH DE ;Save DE LD BC,5 ;Move HL to filename field ADD HL,BC ;Move the pointer ; ; We must now convert the filename in the directory record ; to have the '/' in it. I.E. the entry may look like: ; ; DIR+5 DIR+15 ; +-+-+-+-+-+-+-+-+-+-+-+ ; |F|I|L|E| | | | |C| | | ; +-+-+-+-+-+-+-+-+-+-+-+ ; ; So we must make the name be FILE/C ; LD DE,COMPNAME ;Get the destination LD BC,0B30H ;Number of characters to move ; ; Note that C has a big enough value in it to keep the LDI ; below from changing B which is the loop counter. ; MATCH_1 LD A,(HL) ;See if at the end of name INC HL ;Point a head in case ' ' is next IFA ' ',MATCH_3 ;Skip spaces if at one DEC HL ;Move back, valid character LD A,B ;Check if time for '/' IFANOT 3,MATCH_2 ;If B is 3, then put in a '/' LD A,'/' ;Get the '/' LD (DE),A ;Put it in the destination INC DE ;Point to next position MATCH_2 LDI ;Move the current character MATCH_3 DJNZ MATCH_1 ;Loop until all moved XOR A ;Put in a terminating NULL LD (DE),A POP DE ;Get the wild card pattern back PUSH DE ;Save it again LD HL,COMPNAME ;Get the name to compare against ; ; Now the matching process starts ; ; From C-Kermit's wild carding, this is the function match() ; HL is string, DE is pattern. There are some things different ; here, but this is mostly a line by line translation. ; ; LD A,(HL) ;Check for null strings IFZ NOMATCH ;Return if no match LD A,(DE) ;Check for null pattern IFZ NOMATCH ;Return if no match ; LD (SPAT),DE ;Save current pattern spot LD (SSTR),HL ;Save current string spot LD HL,0 ;Reset the 2 pointers LD (PSAVE),HL LD (SSAVE),HL ; MATCH_6 EQU $ LD HL,(SSTR) ;Get the pointer LD A,(HL) ;Check for end of str IFZ MATCH_9 ;Jump if at the end ; LD DE,(SPAT) ;Ge&t the pattern pointer LD A,(DE) ;Get the character CP (HL) ;Do the characters match JR NZ,MATCH_9 INC HL ;Increment the pointers INC DE LD (SPAT),DE ;Save the new values LD (SSTR),HL JR MATCH_6 ;Loop until done ; MATCH_9 EQU $ LD A,(HL) ;Check if a match was found IFNZ MATCH_10 ;Jump if not at end LD DE,(SPAT) ;Get the pattern pointer LD A,(DE) ;Check if at end of pattern IFNZ MATCH_10 ;Jump if not at end MATCHED CP A ;Set Z status POP DE ;Restore the saved registers POP HL POP BC RET ;Return the matched status ; MATCH_10 EQU $ LD DE,(SPAT) ;Get the pattern pointer LD A,(DE) ;Get the pattern character IFANOT '$',MATCH_12 ;Jump if not '$' INC HL ;++sstr INC DE ;++spat LD (SSTR),HL LD (SPAT),DE JR MATCH_20 ;Skip else case ; MATCH_12 EQU $ IFANOT '*',MATCH_15 ;Jump if not '*' INC DE ;Move pattern forward LD (SPAT),DE ;Save the new value LD (PSAVE),DE LD (SSAVE),HL ;Match Zero characters JR MATCH_20 ; MATCH_15 EQU $ LD HL,(SSAVE) ;Get the saved position LD A,H ;Check if null pointer OR L JR Z,MATCH_17 ;Jump if pointer NULL LD A,(HL) ;Check if end of string IFZ MATCH_17 ;Jump if at the end INC HL LD (SSTR),HL ;sstr = ++ssave; LD (SSAVE),HL ;Save new value LD HL,(PSAVE) LD (SPAT),HL ;spat = psave; JR MATCH_20 ; MATCH_17 EQU $ NOMATCH LD A,1 ;Set NZ status CP 0 POP DE ;Restore the saved registers POP HL POP BC RET ;Return to caller ; MATCH_20 EQU $ JP MATCH_6 ;Loop ; ; This function takes the string in the COMPNAME data area, and ; appends it to the list of filenames already collected. ; COPYFILE EQU $ PUSH DE ;Save the regs PUSH HL PUSH BC LD HL,COMPNAME ;Get name matched LD DE,(FBPTR) ;Get the current position PUSH DE ;Save address to print from COPYF_1 EQU $ LD A,(HL) ;Check for end of string IFZ COPYF_3 ;Jump if at the end LDI ;Move a character PUSH HL ;Save HL PUSH DE ;Copy DE to HL POP HL LD BC,FILEBUFF+BUFFSIZE ;Get the end of buffer OR A ;Reset the carry SBC HL,BC ;Check for too far POP HL ;Restore HL back JR NZ,COPYF_1 ;Loop if not too far STROUT OUTOFSTR ;Print a message JP KERMIT ; COPYF_3 EQU $ PUSH DE POP HL ;Copy DE to HL LD BC,FILEBUFF+BUFFSIZE-4 ;Get max for following OR A SBC HL,BC ;Compute remaining JR NZ,COPYF_5 COPYF_4 STROUT OUTOFSTR ;Print message JP KERMIT ;Abort ; COPYF_5 LD A,':' ;Put in the drive delimiter LD (DE),A ;Store it INC DE ;Point ahead one LD A,(SDIRDRV) ;Get the drive number LD (DE),A ;Store it INC DE ;Point ahead one more LD A,' ' ;Add a space at the end LD (DE),A ;Store it INC DE ;Point ahead LD A,EOS ;Get the end of string character LD (DE),A ;Put in a terminator LD (FBPTR),DE ;Save the new pointer LD HL,FILECNT ;Increment the number of files LD A,(HL) ;Get the current count PUSH AF ;Save the count INC (HL) ;Add one to counter IFNZ COPYF_6 ;Jump if not first LD A,(LOGNAMES) ;Check if should print anything IFZ COPYF_6 ;Jump if not STROUT FILESFND ;Print the message only once COPYF_6 EQU $ POP AF IFA 255,COPYF_4 ;Jump if not too many names POP DE ;Get the string LD A,(LOGNAMES) ;Check if should print anything IFZ COPYF_7 ;Jump if not CALL PRTSTR ;Print the string CALL NEWLIN ;Get a new line COPYF_7 EQU $ POP BC ;Restore the registers POP HL POP DE RET ;Return to caller ; ; Check if any wild card characters are in the string pointed ; to by HL. Return Z status if there are, NZ if there are not ; ISWILD EQU $ PUSH HL ;Save the strings address PUSH DE EX DE,HL ISWILD_1 LD A,(HL) ;Get a character IFZ ISWILD_2 ;End of string? Jump if so IFA '$',ISWILD_4 ;Jump if it is a wild card IFA '*',ISWILD_4 ;Jump if it is a wild card INC HL ;Point to next character JR ISWILD_1 ;Loop until there ; ISWILD_2 EQU $ INC A ;Set NZ ISWILD_3 POP DE ;Restore the registers POP HL RET ;Return to caller ; ISWILD_4 EQU $ CP A ;Set Z status JR ISWILD_3 ;Return ; end of file <<< m4xfer.asm >>> ; M4XFER/ASM ; ; FILE ROUTINES ; ; Output the characters in a packet ; PTCHR LD HL,PUTFILE CALL DECODE JP Z,RSKP RET ; ; Get a packets worth of data ; GTCHR LD A,(EOFLAG) ;Check for EOF OR A ;Set or reset Z RET NZ ;Return if EOF occured CALL GETPKT ;Get a packets worth JP RSKP ;Return saying that something is there ; ; Put a character to a file ; PUTFILE LD DE,(RFIDCB) ;Get the DCB address CALL XPUT ;Output the character RET Z ;Return if no error CALL XERROR0 ;Print an error message LD A,'X' ;Set EOT flag LD (CZSEEN),A RET ;Return to caller ; ; Put a character to the buffer ; PUTDATA PUSH HL ;Save the pointer LD HL,(RMTPTR) ;Get the pointer to the start LD (HL),A ;Store the character INC HL ;Point to next LD (HL),0 ;Terminate the string LD (RMTPTR),HL ;Save the new pointer POP HL ;Restore the pointer CP A ;Set Z status RET ;Return ; ; Get a character from the packet, doing all necessary decoding ; GETDATA PUSH HL ;Save HL LD (RMTPTR),HL ;Store as the place to but the data LD HL,PUTDATA ;Get the address of the routine CALL DECODE ;Decode it POP HL ;Restore HL RET ;Return to caller ; ; Call this address to call the address in HL ; CALLHL JP (HL) RET ; ; Get the next file name pointed to by MFNPTR and put it in FCB. ; If no more names are available, then the Carry Flag will be ; set apon return. Otherwise, NC will exist, and FCB will ; contain a valid TRSDOS filename. ; MFNAME PUSH BC ;Save the registers PUSH DE PUSH HL LD B,32 ;Blank the FCB LD HL,MFREQ PUSH HL LD A,32 MFN0A LD (HL),A INC HL DJNZ MFN0A LD HL,(MFNPTR) ;Get the start of the next name POP DE ;Get the destination CALL XFSPEC ;Move and convert LD (MFNPTR),HL ;Save start of next name PUSH AF ;Save the returned flags LD HL,MFREQ ;Get the source PUSH HL ;Make a copy LD DE,TFILNAM ;Get the destination LD BC,32 ;Get the byte count LDIR ;Move them LD HL,TFILNAM ;Terminate the string with EOS LD A,3 ;Find the ETX LD BC,32 ;Only look this far CPIR ;Find it DEC HL ;Back up to the ETX LD (HL),EOS ;Put in an ETX POP HL ;Restore the source address LD DE,FCB ;Get the FCB destination CALL XFSPEC ;Move a copy into FCB POP AF ;Restore the return flags SCF ;Set initial return flag JR NZ,MFFIX1 ;Abort on error CCF ;Reset Carry to return valid name MFFIX1 POP HL ;Restore the registers POP DE POP BC RET ;Return to the caller ; ; Open the filename in FCB for output ; GETFIL LD A,0FFH LD (FILFLG),A ;No file open XOR A ;Get zero LD (EOFLAG),A ;Not the end of file LD (LSTCHR),A ;No previous character PUSH HL LD DE,FCB ;Get the FCB LD HL,BUFF ;Get the data buffer LD B,0 ;Select LRL=256 CALL XOPEN ;Open the file (at least try) POP HL ;Restore old HL JR Z,GETFIL1 ;Return if normal open ; ; The following code handles files with LRL's different then ; 256. The LRL open fault can be ignored in this case. ; CP 42 ;Check for different LRL ERROR JP NZ,ERRORD ;If not, then error GETFIL1 JP RSKP ;Ignore LRL open fault ; ; PACKET ROUTINES ; ; Send a packet out the comm port ; ; This routine assembles a packet from the arguments given and ; sends it out the communications port ; ; Arguments: ; ; A - TYPE OF PACKET (D,Y,N,S,R,E,F,Z,T) ; ARGBLK - PACKET SEQUENCE NUMBER ; ARGBLK+1 - NUMBER OF DATA CHARACTERS ; SPACK LD (ARGBLK+2),A ;Save data for resend to use LD HL,PACKET ;GET ADDRESS OF THE SEND PACKET. LD A,(SSOHCH) ;GET THE START OF HEADER CHAR. PUTHL A ;PUT IN THE PACKET. LD A,(CURCHK) ;GET CURRENT CHECKSUM TYPE SUB '1' ;DETERMINE EXTRA LENGTH OF CHECKSUM LD B,A ;COPY LENGTH LD A,(ARGBLK+1) ;GET THE NUMBER OF DATA CHARS. ADD A,' '+3 ;Real packet length made printable ADD A,B ;DETERMINE OVERALL LENGTH PUTHL A ;Put in the packet LD B,0 ;ZERO THE CHECKSUM AC. LD C,A ;START THE CHECKSUM. LD A,(ARGBLK) ;GET THE PACKET NUMBER. TOCHAR ;ADD A SPACE SO THE NUMBER IS PRINTABLE. PUTHL A ;Put in the packet CALL NXTSUM ;Get next checksum value LD A,(ARGBLK+2) ;GET THE PACKET TYPE. PUTHL A ;Put in the packet CALL NXTSUM SPACK2 LD A,(ARGBLK+1) ;GET THE PACKET SIZE. IFZ SPACK3 DEC A ;DECREMENT THE CHAR COUNT. LD (ARGBLK+1),A ;PUT IT BACK. LD A,(HL) ;GET THE NEXT CHAR. INC HL ;POINT TO NEXT CHAR. CALL NXTSUM ;Compute next checksum JR SPACK2 ;GO TRY AGAIN. SPACK3 LD A,(CURCHK) ;GET THE CURRENT CHECKSUM TYPE IFA '2',SPACK4 JR NC,SPACK5 ;Go do CRC if '3' LD A,C ;GET THE CHARACTER TOTAL. AND 0C0H ;TURN OFF ALL BUT THE TWO HIGH ORDER BITS RLCA ;TWO LEFT ROTATES SAME AS 6 RIGHTS RLCA ;. . . ADD A,C ;ADD IT TO THE OLD BITS. AND 3FH ;TURN OFF THE TWO HIGH ORDER BITS. TOCHAR ;ADD A SPACE SO THE NUMBER IS PRINTABLE. PUTHL A ;Put in the packet JP SPACK7 ;GO STORE EOL CHARACTER ; ;HERE FOR 3 CHARACTER CRC-CCITT ; SPACK5 LD (HL),0 ;STORE A NULL FOR CURRENT END PUSH HL ;SAVE H LD HL,PACKET+1 ;POINT TO FIRST CHECKSUMED CHARACTER CALL CRCCLC ;CALCULATE THE CRC POP HL ;RESTORE THE POINTER LD C,E ;GET LOW ORDER HALF FOR LATER LD B,D ;COPY THE HIGH ORDER LD A,D ;GET THE HIGH ORDER PORTION RLCA ;SHIFT OFF LOW 4 BITS RLCA ;. . . RLCA ;. . . RLCA ;. . . AND 0FH ;KEEP ONLY LOW 4 BITS TOCHAR ;PUT INTO PRINTING RANGE LD (HL),A ;STORE THE CHARACTER INC HL ;POINT TO NEXT POSITION ; ;HERE FOR TWO CHARACTER CHECKSUM ; SPACK4 LD A,B ;GET HIGH ORDER PORTION AND 0FH ;ONLY KEEP LAST FOUR BITS RLCA ;SHIFT UP TWO BITS RLCA ;. . . LD B,A ;COPY BACK INTO SAFE PLACE LD A,C ;GET LOW ORDER HALF RLCA ;SHIFT HIGH TWO BITS RLCA ;TO LOW TWO BITS AND 03H ;KEEP ONLY TWO LOW BITS OR B ;GET HIGH ORDER PORTION IN TOCHAR ;CONVERT TO PRINTING CHARACTER RANGE PUTHL A ;Store the character LD A,C ;GET LOW ORDER PORTION AND 3FH ;KEEP ONLY SIX BITS TOCHAR ;CONVERT TO PRINTING RANGE PUTHL A ;Store the character SPACK7 LD A,(SEOL) ;GET THE EOL THE OTHER HOST WANTS. PUTHL A ;Store the character PUTHL 0 ;End with a NULL LD A,(DBFLG) OR A JR Z,SPACK8 ;debug is off PUTHL EOS ;Add terminator SPACK8 CALL OUTPKT ;CALL THE SYSTEM DEPENDENT ROUTINE. JP QUIT JP RSKP ; ; WRITE OUT A PACKET. ; OUTPKT LD A,(SPAD) ;GET THE NUMBER OF PADDING CHARS. LD B,A OUTPK2 DEC B JP M,OUTPK4 LD A,(SPADCH) ;GET THE PADDING CHAR. LD E,A ;PUT THE CHAR IN RIGHT AC. CALL OUTCHR ;OUTPUT IT. JR OUTPK2 OUTPK4 LD A,(DBFLG) IFZ OUTPK5 ;If not on, then check for logfile STROUT SPPOS ;Print the SPACK=> message STROUT PACKET+1 ;Print the data OUTPK5 LD A,(DEBLOG) ;See if logging in effect IFZ OUTPK7 ;If not, then finish up LD DE,DFCB ;Get the debug FCB TRLOG SPPOS,OUTPK6 ;Log the SPACK=> message TRLOG PACKET,OUTPK6 ;Log the packet data JR OUTPK7 OUTPK6 XOR A LD (DEBLOG),A LD DE,DFCB CALL XCLOSE OUTPK7 LD HL,PACKET ;POINT TO THE PACKET. OUTPK10 LD A,(HL) ;GET THE NEXT CHARACTER. IFZ OUTPK11 ;Return success if EOS found LD E,A ;PUT THE CHAR IN RIGHT AC. CALL OUTCHR ;OUTPUT THE CHARACTER. INC HL ;INCREMENT THE CHAR POINTER. JR OUTPK10 OUTPK11 LD A,(STURN) ;Is turn around needed? IFZ OUTPK12 JUMP IF NOT NEEDED LD E,A ;Get the character CALL OUTCHR ;Output it OUTPK12 JP RSKP ;Return no error ; ; Compute next checksum ; NXTSUM ADD A,C LD C,A LD A,0 ;Must use load to preserve Carry flag ADC A,B LD B,A RET ; ;THIS ROUTINE WAITS FOR A PACKET TO ARRIVE FROM THE HOST. IT READS ;CHARACTERS UNTIL IT FINDS THE SOH. IT THEN READS THE PACKET INTO PACKET. ; ;RETURNS +1 FAILURE (IF THE CHECKSUM IS WRONG OR THE PACKET TRASHED) ; +3 SUCCESS WITH A - MESSAGE TYPE ; ARGBLK - MESSAGE NUMBER ; ARGBLK+1 - LENGTH OF DATA ; RPACK LD A,(RTIME) ;Get the timeout value LD HL,0 IFZ RPACK1 ;If zero, then no timeout LD L,A ;Get the value as 16 bits LD C,30 ;Get the factor to extend it by CALL XMUL16 ;Do the multiplication LD H,L ;Slide the 24 bit result down LD L,A RPACK1 LD (SVTIMER),HL ;Save it as the timer value RPACK2 CALL STARTTIMER ;Start the timer for receive timeout CALL INPKT ;READ UP TO A CARRIAGE RETURN. JP QUIT ;RETURN BAD. CALL STOPTIMER ;Stop the timeout countdown RPACK3 CALL GETCHR ;GET A CHARACTER. JP RPACK2 ;HIT A CR;NULL LINE; JUST START OVER. CALL CPRSOH ;IS THE CHAR THE START OF HEADER CHAR? JR NZ,RPACK3 ;NO, GO UNTIL IT IS. RPACK4 CALL GETCHR ;GET A CHARACTER. JP QUIT ;HIT THE CARRIAGE RETURN, RETURN BAD. CALL CPRSOH ;IS THE CHAR THE START OF HEADER CHAR? JR Z,RPACK4 ;YES, THEN GO START OVER. LD (PACKET+1),A ;STORE IN PACKET ALSO LD C,A ;START THE CHECKSUM. LD A,(CURCHK) ;GET BLOCK CHECK TYPE SUB '1' ;DETERMINE EXTRA LENGTH OF BLOCK CHECK LD B,A ;GET A COPY LD A,C ;GET BACK LENGTH CHARACTER SUB ' '+3 ;GET THE REAL DATA COUNT. SUB B ;GET TOTAL LENGTH LD (ARGBLK+1),A LD B,0 ;CLEAR HIGH ORDER HALF OF CHECKSUM CALL GETCHR ;GET A CHARACTER. JP QUIT ;HIT THE CARRIAGE RETURN, RETURN BAD. CALL CPRSOH ;IS THE CHAR THE START OF HEADER CHAR? JR Z,RPACK4 ;YES, THEN GO START OVER. LD (ARGBLK),A LD (PACKET+2),A ;SAVE ALSO IN PACKET CALL NXTSUM ;ADD THE CHARACTER TO THE CHECKSUM LD A,(ARGBLK) SUB ' ' ;GET THE REAL PACKET NUMBER. LD (ARGBLK),A CALL GETCHR ;GET A CHARACTER. JP QUIT ;HIT THE CARRIAGE RETURN, RETURN BAD. CALL CPRSOH ;IS THE CHAR THE START OF HEADER CHAR? JR Z,RPACK4 ;YES, THEN GO START OVER. LD (TEMP1),A ;SAVE THE MESSAGE TYPE. LD (PACKET+3),A ;SAVE IN PACKET LD (RECTYP),A CALL NXTSUM ;ADD THE CHARACTER TO THE CHECKSUM. LD A,(ARGBLK+1) ;GET THE NUMBER OF DATA CHARACTERS. LD (TEMP2),A LD HL,DATA ;POINT TO THE DATA BUFFER. LD (DATPTR),HL RPACK5 LD A,(TEMP2) DEC A ;ANY DATA CHARACTERS? JP M,RPACK6 ;IF NOT GO GET THE CHECKSUM. LD (TEMP2),A CALL GETCHR ;GET A CHARACTER. JP QUIT ;HIT THE END-OF-LINE, RETURN BAD. CALL CPRSOH ;IS THE CHAR THE START OF HEADER CHAR? JR Z,RPACK4 ;YES, THEN GO START OVER. LD HL,(DATPTR) PUTHL A ;Store the character LD (DATPTR),HL CALL NXTSUM ;ADD THE CHARACTER TO THE CHECKSUM. JR RPACK5 ;GO GET ANOTHER. RPACK6 CALL CHKECHO ;See if only echo of previous JP RPACK3 ;Yes, restart CALL GETCHR ;Get a character JP QUIT ;HIT THE CARRIAGE RETURN, RETURN BAD. CALL CPRSOH ;IS THE CHAR THE START OF HEADER CHAR? JP Z,RPACK4 ;YES, THEN GO START OVER. SUB ' ' ;TURN THE CHAR BACK INTO A NUMBER. LD (TEMP3),A ;DETERMINE TYPE OF CHECKSUM LD A,(CURCHK) ;GET THE CURRENT CHECKSUM TYPE IFA '2',RPACK9 ;Jump if 2 character JR NC,RPACK8 ;Jump if 3 character ; ; 1 character checksum ; LD A,C ;Get the character count AND 0C0H ;Keep 2 MSB's RLCA ;Move them to 2 LSB's RLCA ADD A,C ;Add the 2 low bits to bottom AND 3FH ;Remove 2 high bits after add LD B,A LD A,(TEMP3) ;GET THE REAL RECEIVED CHECKSUM. IFA B,RPACK10 ;Jump checksum OK RPACK7 CALL UPDRTR ;If checksum bad, update retries RET ;Return error ; ; Here for three character CRC-CCITT ; RPACK8 LD HL,(DATPTR) ;GET THE ADDRESS OF THE DATA LD (HL),0 ;Store a zero in the buffer as terminator LD HL,PACKET+1 ;POINT AT START OF CHECKSUMMED REGION CALL CRCCLC ;CALCULATE THE CRC LD C,E ;SAVE LOW ORDER HALF FOR LATER LD B,D ;ALSO COPY HIGH ORDER LD A,D ;GET HIGH BYTE RLCA ;WANT HIGH FOUR BITS RLCA ;. . . RLCA ;AND SHIFT TWO MORE RLCA ;. . . AND 0FH ;KEEP ONLY 4 BITS LD D,A ;BACK INTO D LD A,(TEMP3) ;GET FIRST VALUE BACK IFANOT D,RPACK7 ;Jump if not correct CALL GETCHR ;GET A CHARACTER. JP QUIT ;HIT THE CARRIAGE RETURN, RETURN BAD. CALL CPRSOH ;IS THE CHAR THE START OF HEADER CHAR? JP Z,RPACK4 ;YES, THEN GO START OVER. SUB ' ' ;REMOVE SPACE OFFSET LD (TEMP3),A ;STORE FOR LATER CHECK ; ; Here for a two character checksum and last two characters of CRC ; RPACK9 LD A,B ;GET HIGH ORDER PORTION AND 0FH ;ONLY FOUR BITS RLCA ;Shift up 2 bits RLCA LD B,A ;Save back into B LD A,C ;Get low order byte RLCA ;Move the 2 MSB's to 2 LSB's RLCA AND 03H ;Save only low 2 bits OR B ;Get other 4 bits LD B,A ;Save back into B LD A,(TEMP3) ;Get this portion of the checksum IFANOT B,RPACK7 ;If wrong, then give up CALL GETCHR ;GET A CHARACTER. JP QUIT ;HIT THE CARRIAGE RETURN, RETURN BAD. CALL CPRSOH ;IS THE CHAR THE START OF HEADER CHAR? JP Z,RPACK4 ;YES, THEN GO START OVER. SUB ' ' ;REMOVE SPACE OFFSET LD B,A ;SAVE IN SAFE PLACE LD A,C ;GET LOW 8 BITS OF CHECKSUM AND 3FH ;KEEP ONLY 6 BITS IFANOT B,RPACK7 ;Jump if bad value RPACK10 LD HL,(DATPTR) PUTHL 0 ;End with a NULL LD A,(TEMP1) ;GET THE TYPE. JP RSKP ; ; Input a packet ; INPKT LD HL,RECPKT ;POINT TO THE BEGINNING OF THE PACKET. LD (PKTPTR),HL INPKT2 CALL INCHR ;GET A CHARACTER. JP INPKT7 ;Skip out if key typed that is valid LD HL,(PKTPTR) ;Get the packet position PUTHL A ;Store the character LD (PKTPTR),HL ;Save the pointer CALL CPREOL ;IS IT THE EOL CHARACTER? JR NZ,INPKT2 PUTHL EOS ;Put in the terminator LD A,(DBFLG) IFZ INPKT3 ;Jump if debug off STROUT RPPOS ;Output RPACK=> message STROUT RECPKT+1 ;Print the received packet INPKT3 LD A,(DEBLOG) ;See if debug log in on IFZ INPKT6 ;Jump if not enabled LD DE,DFCB ;Get the FCB TRLOG RPPOS,OUTPK6 ;Log the RPACK=> message TRLOG RECPKT+1,OUTPK6 ;Log the packet INPKT6 LD HL,RECPKT LD (PKTPTR),HL ;SAVE THE PACKET POINTER. LD A,(RTURN) ;Get the turn around character CALL WAITT ;Go wait for it. JP RSKP ;Return no error ; ; Error return processing. This code deals with the keystrokes ; that are recognized in INCHR(). ; INPKT7 LD A,(CZSEEN) IFANOT 'A',INPKT8 ;Status CALL SHOTRANS ;Show the transfer status JR INPKT16 INPKT8 IFANOT 'B',INPKT9 ;Cancel Batch? LD A,'Z' ;Get the packet type LD (CZSEEN),A LD DE,CBATCH ;Get the cancel message CALL CONDIS ;Print it if not doing REMOTE commands JP INPKT2 INPKT9 IFANOT 'F',INPKT10 ;Cancel FILE? LD A,'X' ;Get the PACKET type LD (CZSEEN),A LD DE,CFILE ;Get the cancel message CALL CONDIS ;Print it if not doing REMOTE commands JP INPKT2 INPKT10 IFANOT 'E',INPKT12 ;Send error, and ABORT? XOR A LD (CZSEEN),A ;Reset the key pressed flag CALL STOPTIMER ;Stop the timer LD A,ABRTMSGLEN ;Get length of message LD (ARGBLK+1),A ;Save the length LD HL,ABRTMSG ;Get the message LD DE,DATA ;Where to put it LD C,A ;Get the length in BC LD B,0 LDIR ;Move the message LD A,'E' ;Get the packet type CALL SPACK ;Send the error packet JP ABORT ;Give up on an error JP KERMIT ;Give up completely INPKT12 IFANOT 'C',INPKT14 ;Cancel transfer, immediately XOR A LD (CZSEEN),A ;Zap the old key pressed CALL STOPTIMER ;Stop the timer JP KERMIT ;Jump to restart INPKT14 IFANOT 'D',INPKT18 ;Toggle debug mode? LD A,(DBFLG) ;Get the debug flag XOR 1 ;Toggle value LD (DBFLG),A ;Store it back INPKT16 XOR A ;Finish up handling, reset key pressed LD (CZSEEN),A ;Reset the flag JP INPKT2 ;Get the next character INPKT18 IFANOT 'H',INPKT20 ;Help? STROUT HELPMSG ;Print the message JR INPKT16 ;Finish up INPKT20 XOR A ;Otherwise, return no input to force LD (CZSEEN),A ;resend to occur... RET ;Return no input packet ; GETCHR LD HL,(PKTPTR) ;GET THE PACKET POINTER. LD A,(HL) ;GET THE CHAR. INC HL LD (PKTPTR),HL CALL CPREOL ;IS IT THE END OF LINE JP NZ,RSKP ;IF NOT RETURN RETSKP. RET ;IF SO RETURN FAILURE. ; ; Assorted comparison routines ; CPSSOH PUSH HL LD HL,SSOHCH CPSH10 CP (HL) POP HL RET CPRSOH PUSH HL LD HL,RSOHCH JR CPSH10 CPSEOL PUSH HL LD HL,SEOL JR CPSH10 CPREOL PUSH HL LD HL,REOL JR CPSH10 CPSPAD PUSH HL LD HL,SPADCH JR CPSH10 CPRPAD PUSH HL LD HL,RPADCH JR CPSH10 CPSTME PUSH HL LD HL,STIME JR CPSH10 CPRTME PUSH HL LD HL,RTIME JR CPSH10 CPSQTE PUSH HL LD HL,SQUOTE JR CPSH10 CPRQTE PUSH HL LD HL,RQUOTE JR CPSH10 ; ;THIS ROUTINE WILL CALCULATE A CRC USING THE CCITT POLYNOMIAL FOR ;A STRING. ; ;USAGE ; HL/ ADDRESS OF STRING ; A/ LENGTH OF STRING ; CALL CRCCLC ; ;16-BIT CRC VALUE IS RETURNED IN DE. ; ;REGISTERS BC AND HL ARE PRESERVED. ; CRCCLC PUSH HL ;SAVE HL PUSH BC ;AND BC LD DE,0 ;INITIAL CRC VALUE IS 0 CRCCL0 LD A,(HL) ;GET A CHARACTER OR A ;CHECK IF ZERO JP Z,CRCCL1 ;IF SO, ALL DONE PUSH HL ;SAVE THE POINTER XOR E ;ADD IN WITH PREVIOUS VALUE AND 0FH ;Keep only 4 bits LD B,0 GETCRCTAB CALL SRLDE4 ;Shift CRC right by 4 XORATHL E INC HL XORATHL D POP HL PUSH HL LD A,(HL) SRL A SRL A SRL A SRL A XOR E AND 0FH GETCRCTAB CALL SRLDE4 XORATHL E INC HL XORATHL D POP HL ;AND H INC HL ;POINT TO NEXT CHARACTER JP CRCCL0 ;GO GET NEXT CHARACTER CRCCL1 POP BC ;RESTORE B POP HL ;AND HL RET ;AND RETURN, DE=CRC-CCITT ; ; Shift DE right by 4 bits ; SRLDE4 SRL D RR E SRL D RR E SRL D RR E SRL D RR E RET ; CRCTAB DW 00000H DW 01081H DW 02102H DW 03183H DW 04204H DW 05285H DW 06306H DW 07387H DW 08408H DW 09489H DW 0A50AH DW 0B58BH DW 0C60CH DW 0D68DH DW 0E70EH DW 0F78FH ; GETNPNT LD A,(HL) INC HL LD (OUTPNT),HL RET ; ; Check if RFIDCB points at FCB. ; CHKFCB LD DE,(RFIDCB) ;Get the current FCB/DCB pointer LD HL,FCB ;Get the Address of FCB OR A ;Reset the carry SBC HL,DE ;Compute the difference RET ;Return the flags ; INCKTRANS PUSH HL ;Save the regs PUSH AF LD HL,(KTRANS) ;Get the current count INC HL ;Add one to it LD A,H ;Check for overflow OR L ;Set the flags LD A,1 ;Set the ok to change curtrans flag CALL Z,ADD64K ;Add 64K if overflow LD (KTRANS),HL ;Save the new counter LD (CURTRANS),HL ;Store as current count too POP AF ;Restore the regs POP HL RET ;Return to caller ; ; Add 64k to the current counter (RTRANS, or STRANS, as well as ; CURTRANS which is used for TRANSACTION logs). ; ADD64K EQU $ PUSH HL ;Save the regs LD L,(IX) ;Get the current Kbyte counter LD H,(IX+1) LD BC,64 ;Add 64 to it ADD HL,BC LD (IX),L ;Store it back LD (IX+1),H IFZ ADD64K_1 LD HL,(CURTRANS+2) ;Get the current value ADD HL,BC ;Add 64 LD (CURTRANS+2),HL ;Store new value ADD64K_1 POP HL ;Restore HL RET ;Return ; ; Wait for the turn around character in A ; TTURN DB 0 ; WAITT OR A ;Check for no turn around RET Z ;return on ZERO LD (TTURN),A ;Save the character WAITT1 CALL INCHR ;Get a character JP INPKT7 ;Process keyboard character LD C,A ;Save the character LD A,(TTURN) ;Check for turn around CP C ;Is the character received it? JR NZ,WAITT1 ;No, get another RET ; SHOTRANS EQU $ STROUT NPKTSTR ;Print number of packets LD HL,(NUMPKT) CALL NOUT STROUT NRTRSTR ;Print retries LD HL,(NUMRTR) CALL NOUT STROUT NCHRSTR ;Print number of characters LD HL,(KTRANS) CALL NOUT STROUT NRECCH ;Number K of characters recvd LD HL,(RTRANS) CALL NOUT LD A,'K' CALL CONOUT STROUT NSNDCH ;Print number of characters sent LD HL,(STRANS) CALL NOUT LD A,'K' CALL CONOUT JP NEWLIN ; CHKECHO PUSH BC LD A,(SNDTYP) LD C,A LD A,(RECTYP) CP C POP BC RET Z JP RSKP ; ; Convert KERMIT filename to TRSDOS filename ; GOFIL LD HL,RMTDATA ;Where to put the name LD A,(ARGBLK+1) ;Number of characters CALL GETDATA ;Get the name in RMTDATA (HL saved) LD DE,MFREQ ;Destination LD BC,8 ;Max characters for first field GOFIL1 EQU $ LD A,(HL) ;At end of field? IFA '.',GOFIL8 ;Jump if at separator IFALT ' ',GOFIL15 ;Stop if at end of string LD A,C ;Check range IFANOT 8,GOFIL2 ;If not first character, then skip LD A,(HL) ;Get the character CALL ISALPHA ;Is it alphabetic? JR Z,GOFIL5 ;Jump if it is LD (HL),'Z' ;Change name JR GOFIL5 ;Join code GOFIL2 EQU $ ;Second or later character... LD A,(HL) CALL ISALNUM ;Is it alphanumeric? JR Z,GOFIL5 ;Jump if so INC HL ;Skip this one JR GOFIL1 ;Go to the next character GOFIL5 EQU $ LDI ;Move the character LD A,B ;Check the remaining count OR C JR NZ,GOFIL1 ;Jump if still OK GOFIL7 EQU $ LD A,(HL) ;Are we at the end yet IFA '.',GOFIL8 ;Jump if at the separator IFALT ' ',GOFIL15 ;Stop it at the end INC HL ;Point to next source character JR GOFIL7 ;Loop GOFIL8 EQU $ LD A,C ;Check the count of characters moved IFANOT 8,GOFIL9 ;Jump if at least one moved LD A,'X' ;Use this as the first character LD (DE),A ;Put it in INC DE ;Point to next slot GOFIL9 LD (HL),'/' ;Put in separator LDI ;Move it too LD BC,3 ;Length of next field GOFIL10 EQU $ LD A,(HL) ;Get the character IFALT ' ',GOFIL15 ;Jump if at the end LD A,C ;Check ranges IFANOT 3,GOFIL12 ;Jump if not first character LD A,(HL) ;Get the character (Must be alphabetic) CALL ISALPHA ;Is it alphbetic? JR Z,GOFIL13 ;Jump if it is LD (HL),'Z' ;Make it alphabetic JR GOFIL13 ;Join other code GOFIL12 EQU $ ;Second or third character in extension LD A,(HL) ;Get the character back CALL ISALNUM ;Is it alphanumeric? JR Z,GOFIL13 ;Jump if so INC HL ;Skip it JR GOFIL10 ;Check the next one GOFIL13 EQU $ LDI ;Move a char LD A,B ;Check the count OR C JR NZ,GOFIL10 ;Loop if OK GOFIL15 EQU $ PUSH DE ;Put dest into HL POP HL PUTHL ':' ;Add the default drive LD A,(DEFDSK) PUTHL A ;Add the drive number LD (HL),EOS ;Add the end of string byte PUSH HL ;Save that address LD HL,MFREQ ;Move the string to the save area LD DE,TFILNAM ;Get the destination LD BC,32 LDIR ;Move the bytes POP HL LD (HL),3 ;Put in FSPEC terminator LD (FCBPTR),HL ;Save the end LD HL,MFREQ ;Validate the filespec LD DE,FCB CALL XFSPEC ;Call TRSDOS JR Z,GOFIL18 ;Jump if OK LD HL,(FCBPTR) ;Get end of string LD (HL),EOS ;Put in print terminator STROUT FCB ;Print the name JP XERROR0 ;Print system error message and return GOFIL18 LD HL,FCB ;Get start LD BC,40 ;Maximum to look LD A,':' ;Find drive spec to index off of CPIR ;Look for it. MUST be there INC HL ;Point after for terminator LD (FCBPTR),HL ;Save it DEC HL ;Back up to just after extension DEC HL LD (DATPTR),HL ;Save it for renaming LD A,(FLWFLG) ;Is file warning on? IFZ GOFIL30 ;Jump if not LD DE,FCB ;Get the file name LD HL,BUFF ;Buffer address LD B,0 ;LRL=256 CALL XOPEN ;Is it there? JR NZ,GOFIL30 ;Jump if not LD DE,INFMS5 ;Print renaming message CALL ERROR3 LD DE,FCB ;Close the file CALL XCLOSE ;Close restores the filename with @FNAME GOFIL20 LD HL,(DATPTR) ;Get the pointer to extension LD DE,FCB ;Get the start OR A ;Reset the carry PUSH HL ;Save it SBC HL,DE ;At the beginning yet POP HL ;Restore it JR NZ,GOFIL21 ;Jump if not LD DE,ERMS16 ;Oops, Can't rename it, stop JP PRTSTR ;Print, and return ; GOFIL21 DEC HL ;Point to previous character LD (DATPTR),HL ;Save the new pointer GOFIL24 LD HL,(DATPTR) ;Get the pointer LD A,(HL) ;Get the character IFALT 'B',GOFIL20 ;Jump if we can't change it DEC (HL) ;Change the file name LD HL,FCB ;Get the source address PUSH HL ;Save it for later LD DE,TFILNAM ;Get the destination LD BC,32 ;Number to move LDIR ;Move them POP DE ;Restore stack and get FCB address LD HL,BUFF LD B,0 CALL XOPEN ;Is it there? JR NZ,GOFIL27 ;Jump if not LD DE,FCB ;Close it up CALL XCLOSE JR GOFIL24 ;Try another name ; GOFIL27 LD HL,(FCBPTR) ;Get the end of the file name LD (HL),EOS ;Add the print terminator STROUT FCB ;Print the new name LD (HL),3 ;Put the @OPEN terminator back GOFIL30 LD DE,FCB ;Get the FCB LD HL,BUFF ;Get the buffer LD B,0 ;LRL=256 CALL XINIT ;Create it or zap old file JP Z,RSKP ;Return on success +4 PUSH AF ;Save error code LD DE,ERMS11 ;Print the error message CALL ERROR3 POP AF ;Get the error code back JP ERRORD ;Print a system error ; ; Restart timer for receive packet timeout ; STARTTIMER PUSH HL ;Save the clobbered regs PUSH DE PUSH BC LD C,0 ;Get no timer flag for next test LD HL,(SVTIMER) ;Get the timer value LD A,H ;Check if not timeout wanted OR L JR Z,STARTT3 ;Don't start timer if none needed LD (TIMER),HL ;Set the real counter LD C,8 ;Get the task slot number STARTT1 CALL XCKTSK ;Check is slot in use JR NZ,STARTT2 LD DE,RECTIME ;Get the TCB PUSH BC CALL XADTSK ;Try to add the task POP BC ;Restore the task slot JR STARTT3 ;Go save slot used STARTT2 INC C ;Get next possible slot IFANOT 11,STARTT1 ;Loop if not at max task slot STROUT NOTIMER ;Print error message LD HL,1 LD (SVTIMER),HL ;Zap timer LD C,0 ;Make sure no timer flag is on STARTT3 LD A,C ;Save task to stop LD (TASKSLOT),A POP BC ;Restore registers POP DE POP HL RET ; ; Stop the timeout task ; STOPTIMER PUSH HL ;Save the registers PUSH DE PUSH BC LD C,8 ;Get the task slot number TASKSLOT EQU $-1 CALL XRMTSK LD HL,0 ;Zero out the timer LD (TIMER),HL POP BC ;Restore the registers POP DE POP HL RET ; ; Check if character in A is alphabetic. Z status means YES, ; NZ status means NO ; ISALPHA CP 'A' ;Check upper case RET C ;Return if less than CP 'Z'+1 ;If less than or equal to Z, then A-Z JR C,ISAL_1 ;Jump to TRUE return CP 'a' ;Check lower case RET C ;Return less than CP 'z'+1 ;Check for a-z RET NC ;NC means greater than 'z' ISAL_1 CP A ;Set Z status RET ;Return ; ; Check if character in A is alphanumeric ; ISALNUM CP '0' ;Check digits RET C ;Return too small CP '9'+1 ;Check max+1 JR NC,ISALPHA ;If too big, go try alphabetic CP A ;Set Z status RET ;return it ; end of file <<< m4mit.doc >>> _T_R_S_-_8_0 _M_o_d_e_l _4_(_p_) _K_E_R_M_I_T_: _V_e_r_s_i_o_n _5_._2 _F_o_r _U_s_e _U_n_d_e_r _T_R_S_D_O_S _6_._1 _o_r _L_a_t_e_r _P_r_o_g_r_a_m _b_y: Gregg Wonderly Oklahoma State University, (gregg@okstate) rewritten from the origi- nal Model-4 KERMIT which was derived from the TRS-80 KERMIT done by Stan Barber, Rice University who modified the CP/M-80 version by Bill Catchings and others. _L_a_n_g_u_a_g_e: Z80 Assembler, compatible with M80 and EDAS from Misosys _V_e_r_s_i_o_n: 5.2 _D_a_t_e: Wed Oct 22 10:17:07 CDT 1986 _D_o_c_u_m_e_n_t_a_t_i_o_n _b_y: Gregg Wonderly _1. _S_u_m_m_a_r_y _o_f _T_R_S_D_O_S _6._1 _T_R_S_D_O_S (The Radio Shack Disk Operating System) has a large library of built in commands dealing with files, directory maintenance, device I/O, etc. Programs are also used for some functions on some _T_R_S_D_O_S-based DOS's. Model 4(p) KERMIT gives you access to all of the library commands of _T_R_S_D_O_S versions 6.x via the LOCAL command. Issue the _L_I_B_R_A_R_Y command at _T_R_S_D_O_S _R_e_a_d_y to obtain a list. _T_R_S_D_O_S file specifications can be represented as a sequence of characters of the form FILESPEC/EXT.PASSWORD:D _F_I_L_E_S_P_E_C is the filename up to eight characters. _E_X_T is the file type, up to three characters. _P_A_S_S_W_O_R_D is the password for that file, up to eight char- acters. _D is a numerical drive specification (0-7). File names, file types and passwords may contain letters and numbers, but the first character in each must be a letter. No special characters or spaces are allowed. All fields are optional except the filespec. Any field added - 2 - must be preceded by its special delimiter '/' for file type, '.' for passwords and ':' for drive specifications. Upper and lower case characters are equivalent. _2. _T_R_S_D_O_S _C_o_m_m_a_n_d_s _o_f _I_n_t_e_r_e_s_t _2._1. _C_A_T _P_A_R_T_S_P_E_C:_D (_O_T_H_E_R _O_P_T_I_O_N_S) This command is specific to _T_R_S_D_O_S version 6.2 and later. It displays only the names of visible files on the drive specified, or all drives if no _p_a_r_t_s_p_e_c is given. (_o_t_h_e_r _o_p_t_i_o_n_s) allows different formats and invisible as well as system files to be selected. See the _T_R_S_D_O_S manual for specifics _2._2. _D_I_R _P_A_R_T_S_P_E_C:_D (_O_T_H_E_R _O_P_T_I_O_N_S) DIR is common to all version of TRSDOS. Versions after 6.1 replaced the DIR command with CAT, and changed the DIR command so that always produces a long listing. _2._3. _F_R_E_E :_D Gives statistics on disk usage. If D is present, it indicates a drive number, and only the statistics for the specified disk will be shown. _2._4. _R_E_M_O_V_E/_P_U_R_G_E _F_I_L_E_S_P_E_C (_P_A_R_A_M_E_T_E_R_S) Remove the file(s) given by FILESPEC from the directory and frees the space allocated to the file for reassign- ment. Purge allows PARTSPECs that specify groups of files. With no PARAMETERS, PURGE prompts before delet- ing any file. REMOVE requires a full filespec as the name of the file to remove. REMOVE allows more than one filespec to be given on the command line. _2._5. _L_I_S_T _F_I_L_E_S_P_E_C (_P_A_R_A_M_E_T_E_R_S) Lists the file on the display. Parameters are described in the _T_R_S_D_O_S manual in detail. (_H_E_X) is sometimes useful to display the hexidecimal values of the characters in a file. _2._6. _R_E_N_A_M_E _o_l_d_f_i_l_e _n_e_w_f_i_l_e Changes the name of oldfile to newfile, provided that newfile is a unique file name on that disk. _3. _C_o_p_y_i_n_g _D_i_s_k_s _a_n_d _F_i_l_e_s: - 3 - _3._1. _C_O_P_Y _f_i_l_e_1 _f_i_l_e_2 Copies file1 and name the copy file2. If file2 exists, it will be replaced. _3._2. _B_A_C_K_U_P :_D :_E Makes a copy of the disk in drive D on the the disk in drive E. _3._3. _F_O_R_M_A_T :_D Formats the disk in drive D. The disk will be ready for any normal read or write operation fol- lowing successful completion of this operation. This operation must be performed before use of a blank disk. Reformatting a previously formatted disk will cause all previously stored information to be lost. _4. _T_r_a_n_s_f_e_r_s _w_i_t_h_o_u_t _t_h_e _K_E_R_M_I_T _P_r_o_t_o_c_o_l Model 4(p) KERMIT adds 2 logical devices to the already resident devices. These devices are used to access the com- munications port. These devices, *FI (File Input) and *FO (File Output), can be used as the source, and destination of a copy command, respectively. They make use of the status of the SET FLOW-CONTROL parameter, to send and receive data using the communications port. For instance, say you are communicating with a computer that does not have KERMIT. Say you also wish to transfer a file to this computer to do some further processing. The normal method involves start- ing a program on the remote computer to collect the data into a file on that system. On a VAX/VMS system, you might use the CREATE command to capture the file. The following _K_E_R_M_I_T commands will accomplish the transmition of a file in this case. OUTPUT CREATE MYPROG.DAT LOCAL COPY PROG/DAT *FO The KERMIT command, OUTPUT, will send the string "CREATE MYPROG.DAT" to the host. Let's say for now that this is sufficient to cause all future characters sent to the host to be placed into the file MYPROG.DAT on that system. The KERMIT command LOCAL is then used to invoke the _T_R_S_D_O_S library command COPY. COPY will copy the contents of the file "PROG/DAT" to the *FO device. The driver for this dev- ice is part of the KERMIT program, and will take care of transmitting the data out of the communications port to the HOST. If the HOST sends XOFF because DATA is arriving TOO fast, then the XON/XOFF option to the _K_E_R_M_I_T command, SET FLOW-CONTROL, will allow the transfer to pause while the HOST catches up. You may wish to collect the contents of a - 4 - file that is on another computer. If particular computer does not have _K_E_R_M_I_T, you can use a series of commands simi- lar to those listed below to retrieve the file. It should be noted that the _S_E_S_S_I_O_N-_L_O_G can also be used to trap the contents of a file. For that very reason, this is only one of several possible ways to get a file from another computer that does not have _K_E_R_M_I_T. OUTPUT TYPE MYPROG.DAT INPUT TYPE MYPROG.DAT LOCAL COPY *FI MYPROG/DAT:1 It may help to clarify the use of the _O_U_T_P_U_T command, and the corresponding _I_N_P_U_T command. If you use the _K_E_R_M_I_T command _C_O_N_N_E_C_T to enter terminal mode, and then proceed to tell the host to type out a file, it may start sending data before you can escape back, and type the _C_O_P_Y command. This means that some of the data would be lost. With _F_L_O_W- _C_O_N_T_R_O_L set to _X_O_N/_X_O_F_F, and the remote host recognizing this fact, the previous commands would not allow any data to be lost. The use of _I_N_P_U_T is only to remove the characters ECHOed by the host from the input buffer (The TEXT of the command "TYPE MYPROG.DAT"). If you are communicating with a half-duplex system in which _M_o_d_e_l (_4)_p _K_E_R_M_I_T is echoing the characters typed on the keyboard, then the _I_N_P_U_T command need not be used. _5. _C_o_n_t_r_o_l _o_f _F_i_l_e _T_r_a_n_s_f_e_r_s _U_s_i_n_g _t_h_e _K_E_R_M_I_T _P_r_o_t_o_c_o_l During the transfer of a file using either _S_E_N_D, or _G_E_T and possibly during the use of the _R_E_M_O_T_E command, protocol operations may need to be aborted, or altered. Several key strokes allow the user to control the protocol operations. These are listed below, and are listed on the screen after issuing either the _S_E_N_D or _G_E_T commands. The operation of the _R_E_M_O_T_E command is purposefully silent. The key strokes are available to the user during _R_E_M_O_T_E commands, for added flexibility. This allows the user to cancel commands like _R_E_M_O_T_E _T_Y_P_E that may otherwise cause large amounts of data to be displayed for an extended amount of time. The valid key strokes are: _C_o_n_t_r_o_l-_F During data transfers using the _K_E_R_M_I_T proto- col, _C_o_n_t_r_o_l-_F will terminate the current transaction. If there are more files to transfer, the next transaction will be started. _M_o_d_e_l _4(_p) _K_E_R_M_I_T will send a sig- nal to the remote _K_E_R_M_I_T telling it to stop sending packets for the current transaction. - 5 - If the remote _K_E_R_M_I_T understands this signal (not all implementations of _K_E_R_M_I_T do), it will comply, otherwise the transaction will continue. _C_o_n_t_r_o_l-_B Like _C_o_n_t_r_o_l-_F, except that if a group of files is being processed this will stop the entire group. If only a single file is being _S_E_N_T or _R_E_C_E_I_V_E_D, _C_o_n_t_r_o_l-_B behaves exactly like _C_o_n_t_r_o_l-_F. _C_o_n_t_r_o_l-_C Aborts the protocol immediately. This should be a last resort to stopping a transmission as it will leave the remote _K_E_R_M_I_T in an unk- nown state. _C_o_n_t_r_o_l-_E Aborts the protocol after sending an ERROR packet to the remote _K_E_R_M_I_T. _C_o_n_t_r_o_l-_D Toggles _D_E_B_U_G mode _O_N and _O_F_F. This is help- ful when trying to figure out why a particu- lar host is unable to talk to _M_o_d_e_l _4(_p) _K_E_R_- _M_I_T. <_E_N_T_E_R> If you type <_E_N_T_E_R>, _M_o_d_e_l _4(_p) _K_E_R_M_I_T will resend the current packet. _C_o_n_t_r_o_l-_H Displays the list of _K_E_Y_S that you may press during a transfer. I.E. the keys described above. This is the same message that is printed when a SEND, GET, or RECEIVE command is issued. _6. _M_o_d_e_l _4(_p) _K_E_R_M_I_T _C_o_m_m_a_n_d_s _M_o_d_e_l _4(_p) _K_E_R_M_I_T uses a subset of the the _D_E_C_S_Y_S_T_E_M-_2_0 keyword style command language. Each keyword may be abbre- viated to its minimum unique length. "?" may be typed to request a list of the available options for the current field at any point in a command. If insufficient characters have been typed to identify the current field uniquely, _M_o_d_e_l _4(_p) _K_E_R_M_I_T will display all available choices, and then reprompt to allow you to continue from that point. If there are sufficient characters, then only a single choice will be displayed. The following list of commands are available when using _M_o_d_e_l _4(_p) _K_E_R_M_I_T. - 6 - _6._1. _B_Y_E When talking to a remote _K_E_R_M_I_T Server, this command should shut down a remote server and terminate the login that you had there. _M_o_d_e_l _4(_p) _K_E_R_M_I_T will then exit to _T_R_S_D_O_S _R_e_a_d_y. NOTE: Due to some deviations from the specifica- tion, some systems do not perform exactly in this manner. You should check the documentation of the _K_E_R_M_I_T on the remote system in order to obtain the operation performed by this command. _6._2. _C_L_E_A_R _6._2._1. _I_N_P_U_T-_P_O_R_T _M_o_d_e_l _4(_p) _K_E_R_M_I_T uses the "Interrupt on received character available" feature of the COM/DVR com- munications line driver. This driver is part of the standard software on your system diskette. All characters received via the interrupt vector, are placed in a 256 byte circular buffer. This command clears all characters currently buffered. This is used most commonly with the INPUT, OUTPUT, PULSE, and PAUSE commands, none of which expli- citly clear the input buffer. YOU MUST DO THIS YOURSELF. The execution of this command will _n_o_t send an _X_O_N character to the communications port. This is also left up to you to do. _6._2._2. _S_C_R_E_E_N As you would expect, this command clears the screen. _6._3. _C_L_O_S_E _6._3._1. _D_E_B_U_G-_L_O_G Closes the file previously opened with the LOG DEBUG-LOG command. If there is not a debug log- file active, then a message is printed telling you so. _6._3._2. _S_E_S_S_I_O_N-_L_O_G Closes the file previously opened with the LOG SESSION-LOG command. If no file is open, you will be advised so. - 7 - _6._3._3. _T_R_A_N_S_A_C_T_I_O_N-_L_O_G Closes the file previously opened with the LOG TRANSACTION-LOG command. As with the other log- files, if a file is not currently open, then a message to that affect is printed. _6._4. _C_O_N_N_E_C_T (_c_a_n _b_e _a_b_b_r_e_v_i_a_t_e_d _t_o '_C') Establish a "virtual terminal" connection to any host that may be connected to the serial port, i.e. pass all typed characters to the serial port and display all input from the serial port on the screen. A two character sequence of characters is required to return the user to the _K_E_R_M_I_T program. An escape character must be typed followed by a 'c' (Case is _n_o_t significant). The default character is entered by pressing the key, and then and key, while hold- ing the key down. Pressing '?' after the character will display a list of valid keystrokes that do helpful things during connect mode. The first time that you issue the _C_O_N_N_E_C_T command, a message will be displayed telling you what the character is. The character should generally be an uncommonly-used control character. The following characters are valid following the <_E_S_C_A_P_E> character, and gen- erate specific actions. The actions are described beside the character. _C Return to _M_o_d_e_l _4(_p) _K_E_R_M_I_T command level. The contents of the screen and the cursor location will be saved prior to displaying the _K_E_R_M_I_T screen. When you reconnect to the _H_O_S_T using the _K_E_R_- _M_I_T command, _C_O_N_N_E_C_T, the old screen will be restored. _? List available single-character com- mands, I.E. These commands. _B Send a TRUE modem break. _R Resume logging if file open, and Q was used previously to turn logging off. See the _L_O_G command for more information. _Q Quit logging to file but leave it open. _0 (_z_e_r_o)Send a null (0) character out the communications port. - 8 - <_E_S_C_A_P_E>Send the <_E_S_C_A_P_E> character itself to the remote host. _6._5. _D_I_R _p_a_r_t_s_p_e_c Produces a listing of the directory for "partspec". If partspec is not given, than the directory will be displayed for the _D_E_F_A_U_L_T-_D_I_S_K drive as established by _S_E_T _D_E_F_A_U_L_T-_D_I_S_K. _6._6. _E_X_I_T Exit _M_o_d_e_l _4(_p) _K_E_R_M_I_T, and return to _T_R_S_D_O_S. Before the _K_E_R_M_I_T program is terminated, all open files will be closed. This includes the LOGFILES used for SESSION, TRANSACTION, and DEBUG logging. The *FO, and *FI devices will also be removed. _6._7. _E_C_H_O This command echoes text given as an argument to the screen. It can used in take files to put mes- sages on the screen when TAKE-DISPLAY is OFF, although other uses are possible. _6._8. _F_I_N_I_S_H Shuts down a remote server without logging it out. Leaves you at _M_o_d_e_l _4(_p) _K_E_R_M_I_T command level. A subsequent _C_O_N_N_E_C_T command will reconnect you to the remote host. The _r_e_m_o_t_e _K_E_R_M_I_T should return to the mode it was in prior to entering _S_E_R_V_E_R mode. _6._9. _G_E_T _f_i_l_e_s_p_e_c Get allows you to retrieve files from a remote host. Get works with either a _S_E_R_V_E_R or a _K_E_R_M_I_T that has initiated a _S_E_N_D command. Filespec is a filename compatible with _t_h_a_t system. When _M_o_d_e_l _4(_p) _K_E_R_M_I_T is talking to a _K_E_R_M_I_T Server, you may include a filespec in a form legal to the _H_O_S_T _K_E_R_M_I_T. _6._1_0. _I_N_P_U_T <_c_o_n_t_r_o_l _s_t_r_i_n_g> INPUT provides one of 4 commands that provide an automatic logon facility. INPUT allows you to watch for the occurrence of certain text strings that are made up characters arriving in the com- munications port. This is useful in _T_A_K_E files that can automatically log you onto a certain sys- tem. - 9 - When _I_N_P_U_T in initiated, it begins matching characters in the input to those given in the con- trol string. When an exact match is found as established by the _S_E_T _I_N_P_U_T options then _I_N_P_U_T will return to the _K_E_R_M_I_T command level. If _T_A_K_E is active than the next line of the _T_A_K_E file will be read. The Control string may be comprised of any printable _A_S_C_I_I characters. _S_P_A_C_E must not occur as either the beginning or end of the string. _A_S_C_I_I character codes 0-32 are denoted as <_N_U_L> - <_S_P_A>, and <_D_E_L> represents character 127. The string <_D_L_Y*> signifies an immediate delay. The * should be replaced by a character. The sig- nificance of the character is this. Decimal 48 is subtracted from the _A_S_C_I_I value of the character to obtain the number of seconds to delay. Thus, you can obtain delays 1-9 seconds, with no trick- ery. Delays longer than that will have to be cal- culated since the formula (ASCII code - 48 decimal) is used to calculate the binary value to use as a counter. The "*" should be replaced with the single proper ASCII character. If you use <_D_L_Y*> in a _P_U_L_S_E command, it should be noted that it will only be done once. An alternative format for control characters is to explicitly type a carat ("^") preceding a charac- ter. The result of subtracting 64 from the _A_S_C_I_I code for the character following will then be used. Since <, >, and ^ now have special mean- ings, you will need some way to specify them explicitly. To do this you should precede them with a backslash, "\", character. In this case, backslash itself now must be represented as "\\". Finally, any and all characters can be represented using a string of the form \nnn where nnn is 1 or more octal digits. nnn is evaluated, and the resulting value will be the ASCII value of the character. Some examples might be: INPUT login: Find the string "login:" followed by a space. INPUT ^M^Jenter \\userid\\: Find the string with a space followed by a carriage return followed by a line feed followed by the text "enter \userid\:" followed by carriage return and another linefeed. - 10 - INPUT USERNAME\77\40 Find the string "USERNAME? ". Note that \77 is the _O_N_L_Y way that a question mark can be specified since a question mark is recognized by the command stream as a request for help. While input is waiting for a match, you may type characters on the keyboard to be transmitted. _B_R_E_A_K will abort the _I_N_P_U_T command and if _T_A_K_E is active, close the take file. _E_S_C_A_P_E will abort the INPUT command, but will just skip to the next line in a _T_A_K_E file, if _T_A_K_E is active. These same 2 actions apply to the _P_U_L_S_E command while no input has been received. _6._1_1. _K_I_L_L _w_i_l_d_s_p_e_c This command performs the task of deleting one or more files from disk. _W_i_l_d_s_p_e_c is a wild card filespec that will be evaluated. All files that match the wildspec will be removed. A _w_i_l_d_s_p_e_c may contain any characters valid is a TRSDOS filespec, plus zero or more occurances of the characters '*', and '$'. These two characters have special meanings. When comparing the _w_i_l_d_s_p_e_c with the name of a file, a '*' matches zero or more of the charac- ters in the filename. E.g. If a file FOO/ASM is compared with '*/ASM', then it would match, because '*' can be thought of as 'FOO', and then '/ASM' is matched literally. M4*/ASM matches M4MIT/ASM, M4XFER/ASM, M4SEND/ASM, and any other filename that begins with M4, and ends with /ASM. The '$' character matches any single character. This means that FILE$/DOC matches the filename FILE1/DOC, but not FILE1A/DOC. A drivespec may be appended to the _w_i_l_d_s_p_e_c to force the search for matches to be restricted to a single drive. An example might be M4*/ASM:1, which limits the matches to those file on drive 1. Normally, only visible, nonsystem files are considered in the search. However, the inclusion of a parameter list containing either, or both of the keywords, INVIS or SYSTEM, will include invisible and/or system files. An example would be: KILL (I,S) config/sys (I) backup/cmd This example would cause _M_o_d_e_l _4(_p) _K_E_R_M_I_T to attempt to remove the two files listed. Note that - 11 - as this example shows, you must specify the param- eters with each _w_i_l_d_s_p_e_c that you wish to apply them to, as they are nullified each time that a new _w_i_l_d_s_p_e_c is evaluated. Other examples are given in the description of the _S_E_N_D command. _6._1_2. _L_O_C_A_L <_T_R_S_D_O_S _l_i_b_r_a_r_y _c_o_m_m_a_n_d> (_C_a_n _b_e _a_b_b_r_e_i_v_i_a_t_e_d _t_o _L) This command allows you to issue commands from within _M_o_d_e_l _4(_p) _K_E_R_M_I_T. You must remember where Model 4(p) KERMIT resides in memory, to assure that you do not overwrite it. KERMIT loads at 6000H, and continues up through LOW$. From within KERMIT, you can issue the command: LOCAL MEMORY to see where KERMIT ends. The value of LOW$ tells you this information. KERMIT was placed at 6000H to allow most of the TRSDOS library programs and commands to work in conjunction with KERMIT. Some commands extend above 3000H, and must have memory available up to approximately 5300H. The COPY command creates a problem because it apparently tries to examine HIGH$ to see if there is space to load a large portion of the source file into memory before writing it to the destination. This creates problems because KERMIT moves LOW$ up so that HIGH$ has a value that will allow additional high memory module to be loaded. It is suggested that you not use COPY while KERMIT is running, as the machine may crash when COPY completes. This is because it will have copied data into the KER- MIT memory space. _6._1_3. _L_O_G _6._1_3._1. _D_E_B_U_G-_L_O_G The debug log can be used to debug transfer problems that sometimes arrise when talking to a newly written KERMIT. The information written to the DEBUG-LOG is nearly identical to that which is displayed on the screen when the command, SET DEBUG ON, is issued, or the CTRL-D key is pressed during a transfer. This file can be closed explicitly with the _C_L_O_S_E _D_E_B_U_G-_L_O_G command. The EXIT command also causes an implicit closing of this file. - 12 - _6._1_3._2. _S_E_S_S_I_O_N-_L_O_G When CONNECTed to a foreign host as a termi- nal, this command establishes a log of the terminal session in the file specified. This function depends, to some extent, on the remote host's ability to do _X_O_N/_X_O_F_F flow control. Without _F_L_O_W-_C_O_N_T_R_O_L, data may be lost when _K_E_R_M_I_T writes to the file. The log file is closed by explicitly typing the _K_E_R_- _M_I_T command _C_L_O_S_E _S_E_S_S_I_O_N-_L_O_G or implicitly when _K_E_R_M_I_T is exited via the _E_X_I_T command. It will also be closed if an I/O error occurs in file processing for the file involved. _L_O_G_G_I_N_G may be toggled on and off during _C_O_N_- _N_E_C_T using the sequence of keys described in the _C_O_N_N_E_C_T description. _6._1_3._3. _T_R_A_N_S_A_C_T_I_O_N-_L_O_G The transaction log is used to keep a record of the files transfered during a KERMIT ses- sion. The information includes whether or not the transaction was SENDING, or RECEIV- ING, the name of the file transfered, and the number of bytes involved in the transfer. _6._1_4. _L_O_G_O_U_T Logout tells a _r_e_m_o_t_e _k_e_r_m_i_t _s_e_r_v_e_r to terminate itself, as well as your login session. When this is completed, you are left at _M_o_d_e_l _4(_p) _K_E_R_M_I_T command level. _6._1_5. _O_U_T_P_U_T <_c_o_n_t_r_o_l _s_t_r_i_n_g> This is the other side of the _I_N_P_U_T command. Con- trol string follows the same conventions as in _I_N_P_U_T, and the resulting character(s) will be out- put to the communications port immediately. It should be noted that _N_O characters other than what you specify are transmitted. In other words if you want to simulate typing some string, followed by pressing <_E_N_T_E_R>, then you will have to use a command similar to: OUTPUT mypassword The <_C_R> will explicitly send the _A_S_C_I_I character 13 to the communications port. - 13 - _6._1_6. _P_A_U_S_E <_n_u_m_b_e_r _o_f _s_e_c_o_n_d_s> This command is usually used in conjunction with _I_N_P_U_T, _O_U_T_P_U_T, and _P_U_L_S_E as a means of syncroniz- ing _M_o_d_e_l _4(_p) _K_E_R_M_I_T to a remote host. A delay of the specified number of seconds will be gen- erated based on the accuracy of the 60HZ inter- rupt. No means has been made for aborting the delay. The maximum delay is 65536 seconds by specifying 0 as the number. _6._1_7. _P_U_L_S_E <_c_o_n_t_r_o_l _s_t_r_i_n_g> This command is an extension/combination of _I_N_P_U_T and _O_U_T_P_U_T. It allows you to transmit one or more characters repeatedly until a character appears in the input port. The use of this command is valu- able when logging onto systems that don't always respond immediately after the reception of some control character(s). For instance, you might (Now that all of the functions of this nature have been described) use the following commands as part of a logon sequence to log onto a computer system. SET INPUT CASE-IGNORE ON SET INPUT DISPLAY ON SET OUTPUT HOST-ECHO ON SET OUTPUT DISPLAY ON CLEAR INPUT-PORT PULSE ^T INPUT XYZ: PAUSE 2 CLEAR INPUT-PORT PULSE INPUT Username: OUTPUT joeblow INPUT Terminal type: OUTPUT h19 SET KEY 8 SET KEY 128 After you study this awhile, it should make sense. If these commands are placed into a _T_A_K_E file, then you could use a _C_O_N_N_E_C_T command after the last command, to connect immediately to the host. If this is done, then _o_n_l_y after you escape back to _M_o_d_e_l _4(_p) _K_E_R_M_I_T, will the _T_A_K_E file finally be closed. _6._1_8. _R_E_C_E_I_V_E <_f_i_l_e_s_p_e_c> This command is synonomous with the GET command. It may be abbreviated to the single character 'R', as in: - 14 - R *.asm _6._1_9. _R_E_M_O_T_E <_c_o_m_m_a_n_d> _R_e_m_o_t_e commands are not supported in totality by all _s_e_r_v_e_r_s. If a _s_e_r_v_e_r supports remote com- mands, then _r_e_m_o_t_e _h_e_l_p should display all of the commands available to the _r_e_m_o_t_e user of the server. Below are descriptions of the _r_e_m_o_t_e com- mands that _M_o_d_e_l _4(_p) _K_E_R_M_I_T knows how to send to a _r_e_m_o_t_e _s_e_r_v_e_r. The arguments to most commands are dependent on the _r_e_m_o_t_e system. You should be familiar with any system before using the _r_e_m_o_t_e _s_e_r_v_e_r commands available from that server. Usu- ally only a small number of these commands are supported since some require abilities that some operating systems just don't have. _6._1_9._1. _C_L_O_S_E-_L_O_G Close a remote _L_O_G previously opened via the command _R_E_M_O_T_E _S_T_A_R_T-_L_O_G. _6._1_9._2. _C_O_P_Y Copy one file to another. _6._1_9._3. _C_W_D <_d_i_r_e_c_t_o_r_y _p_a_t_h> If a particular server's operating system supports the concept of separate directories, then this command will allow you to change to a different directory. _6._1_9._4. _D_E_L_E_T_E Deletes file(s) from the _r_e_m_o_t_e system. Any arguments will probably be file names in the format of the _r_e_m_o_t_e system. _6._1_9._5. _D_I_R Display a list of files on the _r_e_m_o_t_e system. _6._1_9._6. _D_I_S_K Display information about disk utilization on the _r_e_m_o_t_e system. - 15 - _6._1_9._7. _H_E_L_P Get information about _r_e_m_o_t_e capabilities on the _r_e_m_o_t_e system. _6._1_9._8. _H_O_S_T Execute a command on the _r_e_m_o_t_e system. _6._1_9._9. _K_E_R_M_I_T Execute a _K_E_R_M_I_T command on the _r_e_m_o_t_e sys- tem. This command should accept a normal _K_E_R_M_I_T command as an argument. The command, if valid, will then be executed by the remote _K_E_R_M_I_T server. _6._1_9._1_0. _L_O_G_I_N Create a login entity on the _r_e_m_o_t_e system. This may be incorporated into a dedicated server. _6._1_9._1_1. _M_E_S_S_A_G_E Send a message to a user on the _r_e_m_o_t_e sys- tem. _6._1_9._1_2. _P_R_O_G_R_A_M Feed command input to a command executing on the remote system, or control the execution of a program. _6._1_9._1_3. _Q_U_E_R_Y-_V_A_R_I_A_B_L_E Get the value of a variable maintained on the _r_e_m_o_t_e system. _6._1_9._1_4. _R_E_N_A_M_E Change the name of a file on the _r_e_m_o_t_e sys- tem. _6._1_9._1_5. _S_E_N_D-_L_O_G Tells the server to close any open log, and then transfer it to the user. _6._1_9._1_6. _S_E_R_V_E_R-_S_T_A_T_U_S Retrieve certain information about the status of a REMOTE server. The information returned is dependent on the REMOTE system. - 16 - _6._1_9._1_7. _S_E_T-_V_A_R_I_A_B_L_E Set the value of a variable on the _r_e_m_o_t_e system. _6._1_9._1_8. _S_T_A_R_T-_L_O_G Start a transaction log on the _r_e_m_o_t_e system. _6._1_9._1_9. _S_T_O_P-_L_O_G Stops logging to the log file started by the _R_E_M_O_T_E _S_T_A_R_T-_L_O_G command. The file is not closed. Logging may be started again by using the the command, _R_E_M_O_T_E _S_T_A_R_T-_L_O_G. _6._1_9._2_0. _T_Y_P_E Display the contents of the file/files given as arguments. The _r_e_m_o_t_e server should use the _K_E_R_M_I_T protocol to send the contents of the specified file/files to _M_o_d_e_l _4(_p) _K_E_R_- _M_I_T. The file contents will be displayed on the screen using the *SO device. _6._1_9._2_1. _W_H_O Display a list of users on the _r_e_m_o_t_e system. _6._2_0. _S_E_N_D <_w_i_l_d_s_p_e_c> (_M_a_y _b_e _a_b_b_r_e_v_i_a_t_e_d _t_o '_S'); File specifications may contain wild card charac- ters. The recognized wild card characters are '*' and '$'. '*' means zero or more of any character. '$' means exactly one of any character. There are a lot of specifics associated with wild carding, and search order through the drives. When files by the same name exist on dif- ferent drives, a wild card match of one will also match all other occurances. e.g. if drive 0 con- tains the file report/dat, and report.dat also exist on drive 1, then the command other varia- tions can be used to send only one of the 2 files. 'SEND */dat:1' will only match files on drive 1. Another alternative would be Case is NOT significant, so both REPORT/DAT and report/dat are identical. so "*/*" is the same as "*" for all file names with an extension. "*/*", however, does not match names of the form "data", "fred", "file", "temp", or others without extensions. Other examples are given in the - 17 - description of the _K_I_L_L command. _6._2_1. _S_E_T <_p_a_r_a_m_e_t_e_r [_v_a_l_u_e(_s)...]> Set the specified parameter to the specified value. Possible settings: _6._2_1._1. _B_E_L_L _O_N (_o_r _O_F_F) When _D_U_M_B terminal emulation is in effect, a simple noise generator is used to produce a tone like a bell each time the _B_E_L_L character is received. If you don't like it, than use _S_E_T _B_E_L_L _O_F_F to disable it. _6._2_1._2. _B_L_O_C_K-_C_H_E_C_K-_T_Y_P_E The options are: _6._2_1._2._1. _1 (_c_h_a_r_a_c_t_e_r _c_h_e_c_k_s_u_m) Normal, default, standard 6-bit check- sum. _6._2_1._2._2. _2 (_c_h_a_r_a_c_t_e_r _c_h_e_c_k_s_u_m) A 12-bit checksum encoded as two charac- ters. _6._2_1._2._3. _3 (_c_h_a_r_a_c_t_e_r _c_r_c-_c_c_i_t_t) A 16-bit CCITT-format Cyclic Redundancy Check, encoded as 3 characters. The 2 and 3 character options should only be used under conditions of extreme line noise. Many implementations of _K_E_R_M_I_T only support the single character checksum. _6._2_1._3. _D_E_B_U_G_G_I_N_G _O_F_F (_o_r _O_N) When transmitting or receiving packets, con- trols whether the packets are displayed on the local screen. _6._2_1._4. _D_E_F_A_U_L_T-_D_I_S_K <_d_r_i_v_e _n_u_m_b_e_r> The default-drive value is used for received files. The file names created by _M_o_d_e_l _4(_p) _K_E_R_M_I_T will have a ':' and the default drive number affixed to the end so that they will be forced to be saved on the selected drive. - 18 - _6._2_1._5. _E_I_G_H_T-_B_I_T-_Q_U_O_T_I_N_G _O_N (_o_r _O_F_F) This command enables or disables 8th bit quoting. This is useful when a full 8 bit path is available for binary file transfers. _6._2_1._6. _E_M_U_L_A_T_I_O_N _N_O_N_E (_o_r _D_U_M_B) When connected as a terminal to a foreign host, _S_E_T _E_M_U_L_A_T_I_O_N controls whether the Model 4 emulates no terminal, allowing the use of a terminal filter, or whether a _D_U_M_B terminal emulation is used. No emulation is the default. _6._2_1._7. _E_S_C_A_P_E Change the escape character for virtual ter- minal connections. _M_o_d_e_l _4(_p) _K_E_R_M_I_T will prompt you for the new escape character, which you type in locally. _6._2_1._8. _F_I_L_E _6._2_1._8._1. _D_I_S_P_O_S_I_T_I_O_N _K_E_E_P (_o_r _D_I_S_C_A_R_D) When the transfer of a file is inter- rupted, this tells Model 4(p) KERMIT what to do if it receives only a partial file. If FILE-DISPOSITION is DISCARD, then any partial file is removed. Oth- erwise, the file is left as it is when a transfer is interrupted. _6._2_1._8._2. _T_Y_P_E (_A_S_C_I_I _o_r _B_I_N_A_R_Y) Tells _M_o_d_e_l _4(_p) _K_E_R_M_I_T how to deal with the file being sent/received. It is _I_M_P_O_R_T_A_N_T to tell KERMIT if the file is in _A_S_C_I_I when sending to a _N_O_N _M_o_d_e_l _4(_p) _K_E_R_M_I_T. The action taken with this value is as follows. If _A_S_C_I_I mode is set, then CR-LF pairs of characters are translated to CR on input, and CR is translated to CR-LF on output. When binary mode is in effect, this transla- tion does not occur. _6._2_1._9. _F_L_O_W-_C_O_N_T_R_O_L _X_O_N/_X_O_F_F (_o_r _N_O_N_E) When this feature is set to _X_O_N/_X_O_F_F (the default), _M_o_d_e_l _4(_p) _K_E_R_M_I_T will try its best to obey and use _X_O_N characters and _X_O_F_F char- acters for all transmitions through the - 19 - communications port. _N_O_N_E will disable all attempts at this sort of flow- control. _6._2_1._1_0. _I_N_P_U_T _6._2_1._1_0._1. _C_A_S_E-_I_G_N_O_R_E _O_F_F (_o_r _O_N) Controls whether of not case matching is done on characters during the input com- mand. In most instances, you will want this _O_N. _6._2_1._1_0._2. _D_I_S_P_L_A_Y _O_F_F (_o_r _O_N) Controls the display of characters that are input during the execution of the _I_N_P_U_T command. _6._2_1._1_1. _K_E_Y <_k_e_y _v_a_l_u_e> <_s_t_r_i_n_g> This command allows you to send an arbitrary (the length of the _K_E_R_M_I_T command line is the limit) string with a single key stroke. The definition of string is identical for that of the _I_N_P_U_T, _O_U_T_P_U_T, and _P_A_U_S_E commands. KEY VALUE is the ASCII value of the key stroke as given in the TRSDOS manual. If KEY VALUE is not given, then you will be asked to press the key corresponding to the key that you wish to define. All keys are valid in _s_t_r_i_n_g except BREAK. Pressing BREAK signals the end of the definition string. While in _C_O_N_N_E_C_T mode, typing the defined key will cause the characters typed as the definition to be typed instead. Defining a key to have a _N_U_L_L length deletes any previous definition. _6._2_1._1_2. _L_O_C_A_L-_E_C_H_O _O_F_F (_o_r _O_N) When you _C_O_N_N_E_C_T to a remote host, you must set _L_O_C_A_L-_E_C_H_O _O_N if the host is half duplex, _O_F_F if full duplex. _6._2_1._1_3. _O_U_T_P_U_T _6._2_1._1_3._1. _H_O_S_T-_E_C_H_O _O_N (_o_r _O_F_F) When using _O_U_T_P_U_T, and communicating with a remote host, the host commonly echoes the characters as you type. Since _O_U_T_P_U_T effectively types charac- ters for you, these characters may be echoed back. If _H_O_S_T-_E_C_H_O is _O_N, _O_U_T_P_U_T will wait for the echoed character to - 20 - reappear in the input buffer before it sends the next. In the example for send- ing and receiving raw data, that is above, setting _H_O_S_T-_E_C_H_O _O_N, will enable us to remove the _I_N_P_U_T _T_Y_P_E _M_Y_P_R_O_G._D_A_T<_C_R><_L_F> command. Control characters are _N_O_T normally echoed, so this feature when set _O_N, will not wait for them. If you must catch the echo of a control character, then follow the _O_U_T_P_U_T command with the appropriate _I_N_P_U_T command. _6._2_1._1_3._2. _D_I_S_P_L_A_Y _O_F_F (_o_r _O_N) This parameter when on controls the display of characters that are received when _H_O_S_T-_E_C_H_O is _O_N. Otherwise, They are displayed based on the status of the _L_O_C_A_L-_E_C_H_O setting. _6._2_1._1_4. _P_R_I_N_T_E_R _O_F_F (_o_r _O_N) Turns copying of _C_O_N_N_E_C_T session to printer on and off. With _F_L_O_W-_C_O_N_T_R_O_L turned on, and a sending host that will acknowledge the _X_O_F_F, you should have no problems using the printer continuously. _6._2_1._1_5. _R_E_C_E_I_V_E _6._2_1._1_5._1. _E_N_D-_O_F-_L_I_N_E <_A_S_C_I_I _c_o_d_e> Set the end of line character in packets to some other character than <_C_R> which is the default. _6._2_1._1_5._2. _P_A_D-_C_H_A_R <_A_S_C_I_I _c_o_d_e> If the host you are communicating with needs one or more padding characters before it receives actual data during packet transfers, this character will be sent _P_A_D_D_I_N_G times. _6._2_1._1_5._3. _P_A_D_D_I_N_G <_d_e_c_i_m_a_l _n_u_m_b_e_r> The repeat count for the number of times the padding character is transmitted. _6._2_1._1_5._4. _Q_U_O_T_E-_C_H_A_R_A_C_T_E_R <_A_S_C_I_I _c_o_d_e> The character used to quote control characters. The default is pound "#" - 21 - _6._2_1._1_5._5. _S_T_A_R_T-_O_F-_P_A_C_K_E_T <_A_S_C_I_I _c_o_d_e> The character used to syncronize the packets that _K_E_R_M_I_T transmits. By default <_S_O_H>. _6._2_1._1_5._6. _T_I_M_E-_O_U_T <_d_e_c_i_m_a_l _n_u_m_b_e_r> _M_o_d_e_l _4(_p) _K_E_R_M_I_T uses this value as the number of seconds to wait for a response to a packet. If no response is received within the number of seconds given, then the packet for which the response has not been received is retransmitted. _6._2_1._1_5._7. _T_U_R_N-_C_H_A_R The character used to syncronize KERMIT when used over a half duplex line. _M_o_d_e_l _4(_p) _K_E_R_M_I_T will wait for this character at the end of a packet, and will send the SEND TURN-CHAR at the end of a packet. _6._2_1._1_6. _S_E_N_D _6._2_1._1_6._1. _E_N_D-_O_F-_L_I_N_E <_A_S_C_I_I _c_o_d_e> Set the end of line character in packets to some other character than <_C_R> which is the default. _6._2_1._1_6._2. _P_A_D-_C_H_A_R <_A_S_C_I_I _c_o_d_e> If the host you are communicating with needs one or more padding characters before it receives actual data during packet transfers, this character will be sent _P_A_D_D_I_N_G times. _6._2_1._1_6._3. _P_A_D_D_I_N_G <_d_e_c_i_m_a_l _n_u_m_b_e_r> The repeat count for the number of times the padding character is transmitted. _6._2_1._1_6._4. _Q_U_O_T_E-_C_H_A_R_A_C_T_E_R <_A_S_C_I_I _c_o_d_e> The character used to quote control characters. The default is pound "#" _6._2_1._1_6._5. _S_T_A_R_T-_O_F-_P_A_C_K_E_T <_A_S_C_I_I _c_o_d_e> The character used to syncronize the packets that _K_E_R_M_I_T transmits. By - 22 - default <_S_O_H>. _6._2_1._1_6._6. _T_I_M_E-_O_U_T <_d_e_c_i_m_a_l _n_u_m_b_e_r> This value is given to the _o_t_h_e_r host as its' timeout value. You should assure that this is different from the RECEIVE TIME-OUT value so that both timeouts do not occur simultaneously. _6._2_1._1_6._7. _T_U_R_N-_C_H_A_R <_A_S_C_I_I _c_o_d_e> The character used to syncronize KERMIT when used over a half duplex line. _M_o_d_e_l _4(_p) _K_E_R_M_I_T will send this charac- ter at the end of a packet. The RECEIVE TURN-CHAR will be waited for before data is transmitted. _6._2_1._1_7. _T_A_K_E-_D_I_S_P_L_A_Y _O_F_F (_o_r _O_N) Controls the display of _T_A_K_E files as they are executed. By default this feature is off. _6._2_1._1_8. _W_A_R_N_I_N_G _O_N (_o_r _O_F_F) Warns user if filename conflicts when receiv- ing files from remote host, and attempt to generate a unique name by modifying the given one. _O_N by default. _6._2_2. _S_E_T_C_O_M <_T_R_S_D_O_S _S_E_T_C_O_M _c_o_m_m_a_n_d _p_a_r_a_m_e_t_e_r> Sets/shows the status of the communications driver, _C_O_M/_D_V_R. If no arguments are given, than the current status will be shown. Any arguments must be enclosed in parenthesis as the result of this command, is a generated _T_R_S_D_O_S command as in: SETCOM (B=9600,P=N,W=8) The default values are established according to you. If you set up the driver for a certain con- figuration, and then use _S_Y_S_G_E_N to save it, then that will be the default. _N_O sysgen should give you: 300 BAUD EVEN PARITY DTR=YES 7 DATA BITS 1 STOP BIT - 23 - _6._2_3. _S_H_O_W Allows one or ALL of the options of the _S_E_T com- mand to be displayed. Using the "?" feature will aid you if you can't figure out where to find something. All of the things that can be SET can be displayed. The items not listed below can be displayed by using a command like: SHOW BLOCK or SHOW DEFAULT SHOW ALL will display all of the set values except keys. You must use SHOW KEY to see these values. _6._2_3._1. _S_E_N_D Displays all options described under the _S_E_T _S_E_N_D command. _6._2_3._2. _R_E_C_E_I_V_E Displays all options described under the _S_E_T _R_E_C_E_I_V_E command. _6._2_3._3. _K_E_Y <_A_S_C_I_I _k_e_y _v_a_l_u_e> If is specified, then the defin- ition for the specified key number is display. Otherwise, a prompt is issued for the user to type the keystroke that should be taken as the key to display. \nnn is used to display all values greater than 127. ^x where x is a character 64 greater than 0 through 31, and 127 is used to display control characters. Any other printable ASCII character is displayed normally. _6._2_4. _S_T_A_T_U_S Shows certain information about the status of _M_o_d_e_l _4(_p) _K_E_R_M_I_T. Items currently displayed include the amount of space left in the _K_E_Y definition table, the number of bytes written to files during transfers, the number of bytes read from files during transfers, as well as statistics on the latest transfer. _6._2_5. _T_A_K_E <_f_i_l_e_s_p_e_c> TAKE allows commands to be stored in a file, and then executed by the _K_E_R_M_I_T command interpreter. Only _o_n_e level of _T_A_K_E files is supported. This means that a - 24 - _T_A_K_E command can not appear inside of a _T_A_K_E file. No checking is done to enforce this, so good luck if you want to try it. When _K_E_R_M_I_T is first entered, a check is made for a file called _K_E_R_M_I_T/_I_N_I on all of the active disk drives as per normal _T_R_S_D_O_S searching order. If it is found, than it is used as a _T_A_K_E file where you can store initialization commands. Pressing the _B_R_E_A_K key, or the _E_N_T_E_R key during the startup of KERMIT (before the TAKE file is opened) will cause _K_E_R_- _M_I_T to skip processing of the _T_A_K_E file. _7. _S_e_t_t_i_n_g _u_p _t_o _u_s_e _M_o_d_e_l _4(_p) _K_E_R_M_I_T To use _M_o_d_e_l _4(_p) _K_E_R_M_I_T, you need to have your Model 4 set up properly. The program expects that the *CL device will be driven by the COM/DVR Communications Driver that comes with TRSDOS. It also expects that the *SO device is ROUTED to the *DO device, and that the *SI device is ROUTED to the *KI device. The former 2 are the defaults, and in general, you should not worry about them, unless you have changed them. Setting up the *CL device involves typing the command: SET *CL COM/DVR at the _T_R_S_D_O_S _R_e_a_d_y prompt. If you do not do this, you will get a message of the form Can't find *CL DCB from _M_o_d_e_l _4(_p) _K_E_R_M_I_T when it is starting up. The program will return control to TRSDOS after issuing this message, as it is a fatal error. Model 4(p) KERMIT is not a small program. It occupies memory starting at 6000H, and extends up past 0D300H. If you have parts of TRSDOS resident (Using the SYSTEM (SYSRES=....) command), or perhaps other filters or memory resident modules, then you should make sure that they do not extend below the maximum address used by the program. The last memory address used by _M_o_d_e_l _4(_p) _K_E_R_M_I_T can be obtained by using the command LOCAL MEMORY from within the _M_o_d_e_l _4(_p) _K_E_R_M_I_T program. - 25 - _8. _I_n_s_t_a_l_l_a_t_i_o_n To install _M_o_d_e_l _4(_p) _K_E_R_M_I_T, you must obtain the two files _M_4_B_O_O._B_A_S and _M_4_M_I_T._H_E_X. Because of the size of the executable, the hex file could not be placed into a basic program as data statements. Instead, the basic program opens and reads the file _M_4_M_I_T._H_E_X. This file is an _A_S_C_I_I image of the executable. All that needs to be done, is to run the _B_A_S_I_C program which will convert the file back to its original binary format. The resulting executable should probably be called _K_E_R_M_I_T/_C_M_D. Follow the prompts of the BASIC program and there should not be any problems. _9. _B_u_i_l_d_i_n_g _M_o_d_e_l _4(_p) _K_E_R_M_I_T from the Source. The Source for _M_o_d_e_l _4(_p) _K_E_R_M_I_T is in approximately 15 modules. The names of the modules are: M4ADD/ASM Code for miscellaneous routines. M4CMD/ASM Command parser code. M4EQU/ASM Mosts constants are defined here M4FILE/ASM Additional logfile code such as the LOG command, and the CLOSE command. M4GET/ASM Receive file routines + other miscel- lany. M4KEY/ASM Code for handling the SET KEY functions M4LOG/ASM INPUT, OUTPUT, PAUSE, PULSE commands. M4MAC/ASM Macros used in the program M4MIT/ASM Main entry and some command routines. M4PKT/ASM New packet routines for encoding and decoding packets. M4RMT/ASM The base of what will be the remote com- mand. M4SEND/ASM Send file routines. M4SET/ASM Set options routines. M4SHOW/ASM Show settings routines. M4STR/ASM The majority of storage, prompts, and messages. - 26 - M4TERM/ASM Terminal Emulation, and I/O routines. M4WILD/ASM Wild card file name processing. M4XFER/ASM File processing, and some packet stuff. _M_o_d_e_l _4(_p) _K_E_R_M_I_T was developed using the _E_D_A_S assem- bler from Misosys. Other macro assemblers should be able to assemble the program with minor conversions. _M_4_M_I_T/_A_S_M is the main source module. It will call the other source files into the assembly (using the *GET directive) as needed. If any system calls need to be changed, they are all defined in _M_4_A_D_D/_A_S_M for the most part. All of the SVC's are coded in _M_4_A_D_D/_A_S_M as subroutines that are accessed by CALL Xaaaaa, where aaaaa is the name of the _T_R_S_D_O_S supervisor call (SVC) without the "@" sign. If this version is moved to another OS, there are several things that you should consider. The things that come to mind are: 1. Consider the format of the TRSDOS directory struc- ture. The wild card routines depend on this structure for validating directory entries, and for retrieving the file name. 2. There are 2 places where real time counting is required. The delay specified in a PAUSE state- ment can be handled with a counter, as all other processing is halted (except the interrupt tasks) during the pause. Currently, the Real Time Clock task is used to measure the appropriate delay. The other use of a Real Time counter occurs in the Receive packet timeout. This must be handled using asyncronous processes in order to be accu- rate. 3. There exist code at the beginnning and end of the segment that accesses the screen which outputs the bytes 14, and 15 to the *DO device. These are used to force the cursor to be invisible before the screen is accessed, and to then make it reap- pear after the screen access is completed. 4. The interrupt driven receiver must also be delt with. The code in the routine SETINT, establishes the interrupt vector that the *CL driver will call when a "character received interrupt" is gen- erated. 5. In many instances, the characters having values 16, and 17 are used to enable, and disable reverse video respectively. If the driver for *DO does - 27 - not recognize this convention, as the current one does, then these characters must be handled in some manner. I.E. either removed from the source, or filtered from the terminal output stream. The PRTSTR() routine is a good place to mask these characters at, as it is the sole source of output for strings containing these type of characters. It should be noted that _K_E_R_M_I_T/_C_M_D loads into RAM at 6000H. This avoids high memory filters and drivers, and also allows use of _T_R_S_D_O_S library commands that use low memory beyond 3000H, as FORMAT, and BACKUP do. Exclusive use is made of the *DO device for screen output from the KERMIT program, for informational messages and the like. During connect mode, *SI and *SO are used as the input and output devices to allow filters to be attached that will not effect the operation of _M_o_d_e_l _4(_p) _K_E_R_M_I_T during command operations. If you install a different driver or filter it must be compatible in these areas. _1_0. _P_e_r_f_o_r_m_a_n_c_e _S_p_e_c_i_f_i_c_s _o_f _M_o_d_e_l _4(_p) _K_E_R_M_I_T The _M_o_d_e_l _4(_p) _K_E_R_M_I_T has been tested and proven to work properly at 9600 BAUD with flow control on, transfer- ring files between 2 Model 4's. What makes the _M_o_d_e_l _4(_p) _K_E_R_M_I_T perform so well is the idea of flow control, and the interrupt driven receiver. With out these features, I expect that 2400 baud would be the reliable limit. Flow control can be disabled at speeds less than or equal to ~2400 baud, but greater speeds require that flow control be functional in order to protect the integrity of data in the input buffer. _1_1. _T_h_e _H_e_a_t_h _1_9 _F_i_l_t_e_r The files _M_4_H_1_9_1._A_S_M, _M_4_H_1_9_2._A_S_M, _M_4_H_1_9._M_A_C, and _M_4_H_1_9._E_Q_U make up the sources for a Heath 19 terminal emula- tion filter for the TRS-80 Models 4 and 4p. The assembler used was EDAS by Misosys. To build the filter from sources, you need the above 4 files on a disk. _M_4_H_1_9_1._A_S_M is the main source module, and it *GETs all the other necessary files. The structure of the program is pretty simple. Single character (non escape) sequences, are passed to the filtered device via the @_C_H_N_I_O svc. This filter depends on the _T_R_S_D_O_S *_D_O driver being at the end of the chain. Several control characters are merely translated, and then the new values are passed to *DO. - 28 - A multi-character escape sequence is handled by remembering the previous characters that the filter was passed. The previous characters are remembered by the pres- ence of a non-zero value in the contents of _S_T_A_T_E. The value in _S_T_A_T_E represents the address of the code to handle the next character, given the previous string of characters. The filter is relocatable, but _M_U_S_T reside below screen memory because it accesses it directly when performing several of the advanced terminal functions. For this rea- son, it will never load _a_b_o_v_e _F_3_f_f_H. _1_2. _T_h_e _S_E_T_H_1_9 _P_r_o_g_r_a_m The _S_E_T_H_1_9 program allows you to configure a few options that are available to you when using the _H_1_9 _f_i_l_t_e_r. The _S_E_T_H_1_9 program is created from the sources _M_4_H_1_9_S._A_S_M, _M_4_H_1_9._E_Q_U, and _M_4_H_1_9._M_A_C. _M_4_H_1_9_S._A_S_M is the main source module, and will *GET the other 2 files. The program sup- ports a few parameters that are listed below. REMOVE Remove and reclaim if possible. DURATION Length of BELL tone. FREQUENCY Frequency value (bigger value is lower tone) for BELL. BELL Turn audible BELL ON or OFF. BLOCK Block cursor character. CURSOR Normal cursor character. STRIP8 Control display of 8 bit data. HELP Displays information similiar to this. SHOW Displays the current settings of the parameters, this is the default. These options are specified when you invoke _S_E_T_H_1_9, as per the usual TRSDOS 6.x parameter list. An example is shown below: SETH19 (BLOCK=191,CURSOR=23,BELL=ON,SHOW) This command sets the normal CURSOR, and the edit mode CURSOR values, as well as turning the audible bell on. The show parameter causes 2 lines similiar to those below to be printed on the screen. Normal Cursor: 23, Block Cursor: 191 - 29 - Bell: ON, Frequency: 20, Duration: 120 Strip8: ON The REMOVE option takes several things for granted, as it tries to thoroughly remove the device. It assumes that the H19 filter is attached to the *HP device, and that this device is a filter hooked to *SO. Further more, it assumes that *SO is routed to *DO. This particular set up can be used easily if the fol- lowing commands are used to set up the filter: SET *HP H19/FLT FILTER *SO *HP This is assuming that *SO is routed to *DO. The SETH19 com- mand will perform these very operations if you invoke it, and the memory module, $_H_E_A_T_H, is not in place. The other parameters to the SETH19 command can be used to control certain preferable options to the filter. Set- ting _B_E_L_L off causes the filter to flash the screen when it receives an ASCII(7) character. If BELL is set _O_N, then an audible bell is issued when an ASCII(7) is received. When BELL is ON, then the _D_U_R_A_T_I_O_N, and _F_R_E_Q_U_E_N_C_Y parameters take effect. These 2 parameters select the length and pitch, respectively, of the BELL tone. The FRE- QUENCY value is used as a delay between oscillations of the sound port, so the bigger the number, the lower the tone will be. The _d_e_f_a_u_l_t _D_U_R_A_T_I_O_N is set to 20, and the FREQUENCY is set to 125. You can adjust them as you please. The DURA- TION is inversely proportional to the FREQUENCY, since the delay caused by the FREQUENCY value is part of the overall DURATION of the sound. This means that as you increase FRE- QUENCY, you must _d_e_c_r_e_a_s_e DURATION to maintain the same length of BELL, and vice-versa. The _B_L_O_C_K and _C_U_R_S_O_R parameters are used to control the characters that are used as the cursor by the H19 filter. The H19 terminal has the ability to use a visual mode cur- sor, or a line mode cursor. Since the normal visual mode cursor is usually a block cursor, the parameter BLOCK is used to set the ASCII value of the visual mode cursor. The CURSOR parameter sets the normal line mode cursor. The switch between cursors must be done by the HOST computer that is attached to the Model 4's communications port. There is no magic to when the BLOCK cursor is selected, see the description of the recognized control sequences below. - 30 - The STRIP8 parameter controls whether or not data is printed on the screen with the eighth bit set. Normally, the filter now trims the eighth bit off so that parity can be ignored. The command SETH19 (STRIP8=NO) will cause the eighth bit to not be stripped. That is to say, data will be used as it is received by the filter. Note that when this is done, some control characters with parity bits attached may not be recognized. _1_3. _F_u_t_u_r_e _m_o_d_i_f_i_c_a_t_i_o_n_s It should be fairly straight forward to build extra states into the filter so that it will recognize the ANSI 3.64 sequences for the operations the filter knows how to perform. Full support of all the ANSI 3.64 sequences would be a non-trivial investment in time. The best bet here would, be a completely new device driver, since the overhead of going to *DO is already costly, and trying to implement scroll regions with *DO would be a HACK at best. If some- body wants to do the conversion, I would like to have a copy of the result. _1_4. _H_E_A_T_H-_1_9 _f_i_l_t_e_r _c_a_p_a_b_i_l_i_t_i_e_s The HEATH-19 terminal supports several advanced video capabilities that make it an ideal source for a terminal emulation package. Below is a list of the functions sup- ported by the Model 4(p) H-19 emulator, and the escape sequences that perform the operations. _1_5. _H_e_a_t_h/_Z_e_n_i_t_h-_1_9 _C_o_n_t_r_o_l _C_o_d_e_s The Heath/Zenith-19 terminal is equivalent to the DEC VT52 with extensions for line and character insertion and deletion. Items marked with an asterisk are not currently supported by Model 4(p) H19 emulation. Cursor Functions Sequence Mnemonic Definition ESC H HCUH Cursor Home ESC C HCUF Cursor Forward ESC D HCUB Cursor Backward ESC B HCUD Cursor Down ESC A HCUU Cursor Up ESC I HRI Reverse Index *ESC n HCPR Cursor Position Report ESC j HSCP Save Cursor Position ESC k HRCP Set Cursor to Previously Saved Position - 31 - ESC Y HDCA Direct Cursor Addressing, 1-based: 31+line# 31+col# (same as VT52) Erasing and Editing Sequence Mnemonic Definition ESC E HCD Clear Display (Shift Erase) ESC b HBD Erase Beginning of Display ESC J HEOP Erase to End of Page (Erase Key) ESC l HEL Erase Entire Line ESC o HEBL Erase Beginning of Line ESC K HEOL Erase to End of Line ESC L HIL Insert Line ESC M HDL Delete Line ESC N HDCH Delete Character ESC @ HEIM Enter Insert Character Mode ESC O HERM Exit Insert Character Mode Configuration Sequence Mnemonic Definition *ESC z HRAM Reset to Power-Up Configuration *ESC r Bn HMBR Modify Baud Rate: Bn= A=110, B=150, C=300, D=600, E=1200, F=1800, G=2000, H=2400, I=3600, J=4800, K=7200, L=9600, M=19200 ESC x Ps HSM Set Mode(s): Ps= * 1 = Enable 25th line * 2 = No key click * 3 = Hold screen mode 4 = Block cursor 5 = Cursor off * 6 = Keypad shifted * 7 = Alternate keypad mode 8 = Auto line feed on CR 9 = Auto CR on line feed ESC y Ps HRM Reset mode(s): Ps= * 1 = Disable 25th line * 2 = Enable key click * 3 = Exit hold screen mode 4 = Underscore cursor 5 = Cursor on * 6 = Keypad unshifted * 7 = Exit alternate keypad mode 8 = No auto line feed 9 = No auto CR - 32 - *ESC < HEAM Enter ANSI Mode Modes of Operation Sequence Mnemonic Definition *ESC [ HEHS Enter Hold Screen Mode *ESC \ HXHS Exit Hold Screen Mode ESC p HERV Enter Reverse Video Mode ESC q HXRV Exit Reverse Video Mode *ESC F HEGM Enter Graphics Mode *ESC G HXGM Exit Graphics Mode *ESC t HEKS Enter Keypad Shifted Mode *ESC u HXKS Exit Keypad Shifted Mode *ESC = HAKM Enter Alternate Keypad Mode *ESC > HXAM Exit Alternate Keypad Mode Additional Operations Sequence Mnemonic Definition *ESC } HDK Keyboard Disable *ESC { HEK Keyboard Enable *ESC v HEWA Wrap Around at End of Line *ESC w HXWA Discard at End of Line *ESC Z HID Identify as VT52 (ESC / K) *ESC ] HX25 Transmit 25th Line *ESC # HXMP Transmit Page Enhanced Character Support ESC [ p1 ; ... pn m Set Graphics Rendition where p1, ..., pn are chosen from the following: *0 Reset to normal character display. *1 Display characters in high intensity. *4 Display characters underlined. *5 Display characters blinking. *7 Display characters in reverse video. The Heath-19 transmits the following sequences, but it will not respond to them if they are received. Model 4(p) Kermit will transmit them only if they are programmed with SET KEY. ESC S HF1 Function Key #1 ESC T HF2 Function Key #2 ESC U HF3 Function Key #3 ESC V HF4 Function Key #4 ESC W HF5 Function Key #5 ESC P HF7 Function Key #7 - 33 - ESC Q HF8 Function Key #8 ESC R HF9 Function Key #9 My thanks to Michael Carter and Roland Stolfa for their help in testing and debugging this implementation. Gregg Wonderly Department of Computing and Information Sciences Oklahoma State University UUCP: {cbosgd, ea, ihnp4, isucs1, mcvax, uokvax}!okstate!gregg ARPA: gregg@A.CS.OKSTATE.EDU <<< m4mit.hex >>> 05064B45524D495401020060ED7322D33124D5CD008AFD228BBA210EBB110FBB0180073620EDB0 0601210000CDC189C282602289BA218CDECDC189C282601E43164CCD408A228FBA20311E531649 CD408A2291BA202E1E53164FCD408A2293BA2027CD708AAF329AD9CD8E6011F4AACD026ECDCD8B CD9760C3EE61115FABCD026EC32562117BAB18F5116DAB18F0CD518A1120AACD026EC3478AD511 28CDCD026ED1C93124D5119AD91ACB7FC483891120C7CDB864112BCD3E01CD2A65C3D461219760 E5E521C1604F060009E9C3D48CC3E661C3C76BC39363C38577C33B7DC3A168C3966EC3046FC385 62C3D162C32763C3218BC3638BC3A661C38C61C35661C36592C3D891C3E993C3539301020061C3 2861C34163C309613E05118DD6D5CD2A65C3DD61E14F0600093600CDCF8A118DD6CD026EC39760 3E01119DD0CD2A65C3D461326ED83E04CD2A65C3DD613A6ED84FB72006CD0E8BC39760FE03C2D4 61CD8E60C397601169BA3E02CD2A65C3DD61B7CADD61FD2A8BBAFDCB12C62115C31169BA0600CD 6E8920083E013265BAC39760CD518AAF3265BAC397603E051120C6CD2A65C3DD61CDCF8A3E0D12 2119C6CD2A8AC397602A1CD37E23FE2028FAFE0D2804FE3F2013E5FDE1FD36FF4CFD360049FD36 0142FD36020D2BCDCF8ACD2A8AC397601132C7CD026EC397601161C7CD026EC397603E04CD2A65 C3DD61119AD91ACB7FC4838911C2D93A2AD5B7C48301020062891112DA3A2BD5B7C483891169BA 3A2CD5B7C483890E04FD210000ED5B8FBACD9189CD8E602A89BA0601CDC1892A7A8CCD4F622AC9 8CCD4F62CDC187ED7B22D3210000FD2A8BBAFDCB126EC0C3478A060836002310FBC93E413288D6 CDCF8A3A63DE4F0600218DD6E53E00CDCD73D1C3026ED5CDCF8AD1C3026EB7C8C3518ACD026EC3 CF8A3E04CD2A65C3DD61CDCF8ACD0E8BAF3264D53E31325AD5CD4E80AF3262DE3E013263DE218D D636463E47CDA981C39C62CDB482C39C62FE59CA9760FE452006CD5C62C39760FE4EC48F6D18CB 3E04CD2A65C3DD61CDCF8ACDE562C33B63C39760AF3264D5CD0E8B3E31325AD5CD4E80AF3262DE 3E013263DE218DD601020063364C3E47CDA981C32163CDB482C3F162FE59CA9564FE45CA5C62FE 4EC48F6D18D01176C8C3026E3E04CD2A65C3DD61CDCF8ACDE562C33B63C3EE61CDCF8AC39760CD 5D64B7201E3A2AD5B7280FAF322AD511C2D9CD8389C4518A180611D8BACD026EC39760FE012015 3A2BD5B728EDAF322BD51112DACD8389C4518A18E43A2CD5B728D8AF322CD511EAD9CD8389C451 8A18CFCD5D64B7CAE563FE02CA23643A2BD5B7280911BBBACD026EC397601112DAD53E02CD2A65 C3DD61B7200B2189AF1112DA012000EDB0D12162DD0600CD6789280AFE2A2806CD518AC397603E 01322BD5C397603A2AD5B72803C3A5633E0211C2D9D5CD2A65C3DD61B7200B217DAF0102006411 C2D9012000EDB02162DBD10600CD67892804FE2A20C0AF32D5AF3E02322AD5C397603A2CD5B728 03C3A5633E0211EAD9D5CD2A65C3DD61B7200B2173AF11EAD9012000EDB0D12162DC0600CD6789 2804FE2A20823E01322CD5C397603E011175D0CD2A65C3D461C93E00C36E64E5D53275647EFE00 280CE5D5CDAD89D1E120082318EFD1E1C39564CD518A11C8AACD026ED1E1C9E1232323E9E5C5D5 1193AFD5CD158AEB3600E13E20BE20032318FAEBCD026ED1C1E1C9E1E52212D2ED7310D2ED5314 D22118D2221AD3221CD3AF320DD2320ED22F320FD23A65BAB728063AD0AFB7280ACDCF8AED5B14 D2CD026EC9ED7B10D22118D2221CD33EFF320FD22A0102006512D2E9ED7B10D22118D2221AD322 1CD3CDCF8AAF320DD2320ED23EFF320FD2ED5B14D2CD026E2A12D2E9320CD2CD0968FE06CA9765 FE04CAF165FE01CA2C66FE02CAB267FE10CAB267FE03CAB267FE05CA5A6511C4D1CD026EC9EB22 16D20600CD4368B7F28365E67FFE1BC8FE3F281EFE20280F782A16D2360DEBC39564210DD23600 042A16D277232216D218D2112CA9CD0B66C3F0640600210000229AAFCD4368B7F2B765E67FFE1B C8FE3F283978ED5B9AAFC3956404E5D5C52A9AAF0E0AF5CD318A656FF1D630F2D865C1D1E1114B C7CD026EC39760FE0A30F04F060009229AAFC1D1E118B71164A9CD0B66C3F064CD4368B7F0E67F FE3F20091160C9CD010200660B66C3F064FE1BC8C39564CD026EAF320DD2CDCF8AED5B14D2CD02 6E2A1AD32B3600221AD31118D2CD026EC9ED5316D21A471313ED531ED32A1CD32220D378B7C82A 1ED3235E231D7BFEFFFA5C67CD4368B7F25267E67FFE3FC22767E5D5AF320DD2119ABACD026E21 0ED235D1E12A16D246237E32A2AFAF32A3AF237E3299AF234E7932A1AF23221ED3ED5B20D31AFE 3F2816CD776713BE2320600DF28E661AFE3F2805FE00C3FB663A99AFB72841D5E5C5ED5B1ED3CD 90683AA2AF473AA3AF80473AA4AFB838097832A3AF3AA2AF1809CDCF8A3AA2AF32A3AF914FC5ED 5B1ED3CD026EC13E20CD8F6D0D20F8C1E1D13E03815F1600191083180A2BF2F0662801020067EF AF320DD2CDCF8ACDCF8AED5B14D2CD026E2A1CD336002A1AD32B221AD31118D2CD026EC3F064FE 1BC8E5D5CD8267C344672A1AD30118D2B7ED4211E7D1CD026EC30365D1E11C160019235E23567B C39564CD7767BE200423C3476616007BB7F2656716FF1923232323221ED3052A20D3221CD3C33E 66FE613806FE7B3002E65FC905F81C4B7BB7C81600191E04194623EB2A1ED3237E914FB82801F0 2A20D30DFA9564EB4623EB7E23CD7767B8C0C3A067ED5318D31120C60600CD4368B7F2D467E67F FE1BC8FE3F200E1144A9CD0B66C3F06412130418E23E0D1278B7281EE52120C6ED5B18D3CD6089 C20568EB3E03012800EDB1212700B7ED4245E1221C01020068D378C39564E1C3518AF5D5E53A0D D2B7202D2A1AD3E51118D2B7ED5245E1CD2388DA036578320ED24806002118D2E509221AD3C1B7 ED42CA03653EFF320DD2E1D1F1C9E5C53A0DD2B7CC09682A1CD37E23221CD3FE202804FE092011 3A0FD2B720E33EFF320FD23E20C1E11820F5AF320FD2F1C1E1FE1B2814FE3F2807FE0D2803FE0A C0E52A1CD32B221CD3E1F680C9F5D50100001AFE002804130318F7D1F1C91147CE3E113247CE3E 133248CE3E01CD2A65C3D46121BE684F060009E9C35B6AC3756AC3F36AC3A66AC38F69C37E6AC3 E16AC3EA6AC3D78AC38669C3AF69C3B269C3166BC36769C31969C34069C310691154CF3E01CD2A 65C3D461326ED83E0102006904CD2A65C3DD613A6ED832B6AFC39760CDFC6A32D0AFC397603E01 115BD1CD2A65C3D4614FFE002009CDFC6A32CD9DC39760FE03C2DD61CDFC6A32D3AFC397603E01 113FD1CD2A65C3D4614FFE002009CDFC6A32CF9DC39760FE03C2DD61CDFC6A32D4AFC3976011B9 D03E01CD2A65C3D461326ED83E04CD2A65C3DD613A6ED83268BAC39760CDFC6A328EBAC3976011 90D13E01CD2A65C3D461326ED84F3E04CD2A65C3DD613A6ED83259D5C39760AF18023E0132B5BA 11D1D03E01CD2A65C3D46121CA694F060009E9C3FF69C3DF69C32E6AC33A6AC3406AC3466AC334 6A3E06CD2A65C3DD61B7CAD4617AB728091110BACD026EC397607B324DD5C39760210102006A4F D522B9BA3E06CD2A65C3DD61B7CAD4617AB728091110BACD026EC397602AB9BA3AB5BAB7CC4F6A C4506AC397602153D5C3026A2157D5C3026A214BD5C3026A2151D5C3026A2155D5C3026AC30E8A 2373C9E56F2600CD9A64E1C93E04CD2A65C3DD6111A1C9CD026ECD238A3234D5CD048CC39760CD FC6A322DD5C397601161D03E01CD2A65C3D461326ED83E04CD2A65C3DD613A6ED8322FD5C39760 CDFC6A3230D5C39760112DCF3E01CD2A65C3D4614F060021B96A09E9C3F168C3C26AC39D6A1179 D13E01CD2A65C3D461326ED83E04CD2A65C3DD613A6ED83231D5C39760CDFC6A3233D5C39760CD FC6A3232D5C39760CDFC6A32AAAFC3976011A4D13E0102006B01CD2A65C3D461326ED83E04CD2A 65C3DD613A6ED8C93E06CD2A65C3D461B7285D7AB720507B320CBA3E051187D5ED53CDAFCD2A65 C3DD61218DD6220DBAF5AF320FBAF1B7281ECD1D962019CDD994C297605F3ACB9DB72806AF32CB 9D18E87BCDB86B18E2218DD63A0FBA473A0CBACD1F91C397601110BACD026EC3976011F9ABCD02 6ECD0D6EB728FA320CBACD17741117ACCD026E218DD60600CD0D6EB728FAFE80280D77CD177404 3EFFB828032318E978320FBA18ADE52A0DBA7723220DBA210FBA34E1C93E04CD2A65C3DD61CD3F 8C3A97BA3298BA3E503297BA3A12C3B7201A1128CDCD026E11D3C8CD026ECD048C11F5C8CD026E 3E013212C33E0ECD0102006C8F6D3E1E326C6CCD586CCD776CC3976018F0E52A17C63A15C6BD28 35F37E324D6C2C2217C62166BA35FB3A68BAB7281CC54E3A67BAB728133A97BACB3FB9380BD51E 11CD136EAF3267BAD1C13E00BFE1C9AF3266BA3CE1C9CD126CC05FCD816D3A33D5B7C45C6D7BCD 9E6D06001001C978326C6CC3586CCDFA90C295645F3A34D5BBCAA06CFE802006CD636DC395647B D5CD7B6DD13A2DD5B77BC49E6DC39564CDFA9020FB47E65FFE43200ACD588C3A98BA3297BAC978 FE3F20403E0FCD8F6D0604CD9F89E52100260606CD9F8921000CCD916E3E1FCD8F6D11C2C9CD02 6ECDFA9020FBE1F5E52100260605CD9F89E1CD916E3E0ECD8F6DF118AAE65FFE42200102006D06 CD636DC3956478FE3020081E00CD136EC39564583A34D5BB283678E65FFE5120163A2AD5FE0220 073D322AD5C395643E07CD8F6DC39564FE52200E3A2AD5FE0120ED3C322AD5C395647BCD7B6DC3 9564CD136E3E07CD8F6DC395647BD5CD9889D1C90E01ED5B8FBACD9189F30158980B78B120FBFB 1E00C3136EB7C85FC3136EF5D55F3A2AD5B77BC42089D1F1C9D5C5F5FE07284ECD388AC178C1D1 C9D5C5F55F3A2FD5B728237BFE20301E21D6AF06004F097EB7281B5FFE0C2005CD8E601811FE07 2005CD8F6D18087BED5B93BACDAD89C178C1D1C9D5C5ED5B91BACDA689C1D1C93A8EBAB728AFC5 0E323E01D390068210FE3DD390068210FE0D20EEC10102006E18971AFE00C8B7C48F6D1318F5D5 CD1C8AD1C9D5C54B3ACFAFB7280BCD0D6EFE8020F3AF32CFAF79ED5B8FBACDAD8920F7C1D1C9AF 32446ECD0D6EB72009CD126CCA95640018EDFE0D200A3AC587B7C84FCDEB89C9FE022818FE0628 14FE012810FE05280CFE042808FE082804FE0320C7C640325CD5C9E5F52AB79C2B22B79C7CB520 0A3EC932446EF1E1C3F289F1E1C90603C39F893E333247CE3248CE3E01113FCECD2A65C3D461FE 242815FE092811326ED83E04CD2A65C3DD61CDCF8A3A6ED821CE6E4F060009019760C5E9C3BA73 C3FB72C35371C32073C3A273C30A73C39373C38473C36373C3EC72C36272C3D871C3D073C3C271 C38071C3A171C3440102006F71C3286F3E04CD2A65C3DD611158ACCD026E21FBB9ED4BFAB1B7ED 42CD9A64CDCF8ACDEC85C3976011AFCACD026E2113001185CBCD5C743A8EBACDB874CDCF8A2115 001156CCCD5C742151D5CD7974211300118CCBCD5C743A33D5CDB874CDCF8A2115001165CCCD5C 742157D5CD79742113001196CBCD5C743A32D5CDB874CDCF8A2115001174CCCD5C74214FD5CD79 7421130011A2CBCD5C743A31D5115CCBB728031164CBCD026ECDCF8A2115001185CCCD5C742155 D5CD797421130011AECBCD5C743A2DD5CDB874CDCF8A2115001196CCCD5C74214BD5CD79742113 0011BBCBCD5C74CDD788CD048CCDDC88CDCF8A21150011A8CCCD5C74214DD5CD79740102007021 130011C9CBCD5C743A30D5CDB874CDCF8A21150011BACCCD5C742153D5CD797421130011D8CBCD 5C743A68BA114ACBB720031155CBCD026ECDCF8A11DDCACD026E21130011E7CBCD5C74CDD7883A 29D5CD8F6DCDDC88CDCF8A21150011CDCCCD5C743AD3AFCDA974012006CDA074CD737421130011 F7CBCD5C743A2FD51155CBB72803116DCBCD026ECDCF8A21150011DECCCD5C743ACD9DCDA97401 2006CDA074CD73742113001108CCCD5C74CDD7883AB6AF1174CBB72003117ECBCD026ECDDC88CD CF8A1109CBCD026E211300111BCCCD5C74CDD7883A59D5CD8F6D110DCDCD026ECDDC88CDCF8A21 150011EDCCCD5C743AD4AFCDA974012006CDA074CD010200717374211300112ECCCD5C743AD0AF CDB874CDCF8A21150011FFCCCD5C743ACF9DCDA974012006CDA074CD73742113001142CCCD5C74 3AAAAFCDB874CDCF8ACDCF8AC39760112ECCCD026E3AD0AFCDB874C3CF8A1142CCCD026E3AAAAF CDB874C3CF8A1108CCCD026ECDD7883AB6AF1174CBB72003117ECBCD026ECDDC88C3CF8ACDCF8A 11DECCCD026E3ACD9DCDB874CDCF8A11CDCCCD026E3AD3AFCDB874C3CF8ACDCF8A11FFCCCD026E 3ACF9DCDB874CDCF8A11EDCCCD026E3AD4AFCDB874C3CF8A11D8CBCD026E114ACB3A68BAB7C202 6E1155CBC3026E3E04CD2A65C3DD61CDCF8A2115001156CCCD5C743A51D5CD526ACDCF8A211500 1165CCCD5C743A5701020072D5CD526ACDCF8A2115001174CCCD5C743A4FD5CD526ACDCF8A2115 001185CCCD5C743A55D5CD526ACDCF8A2115001196CCCD5C743A4BD5CD526ACDCF8A21150011A8 CCCD5C743A4DD5CD526ACDCF8A21150011BACCCD5C743A53D5CD526ACDCF8AC93E04CD2A65C3DD 61CDCF8A2115001156CCCD5C743A52D5CD526ACDCF8A2115001165CCCD5C743A58D5CD526ACDCF 8A2115001174CCCD5C743A50D5CD526ACDCF8A2115001185CCCD5C743A56D5CD526ACDCF8A2115 001196CCCD5C743A4CD5CD526ACDCF8A21150011A8CCCD5C743A4ED5CD526ACDCF8A21150011BA CCCD5C743A54D5CD526ACDCF8AC91185CBCD026E3A8EBACDB874C3CF8A11AECBCD02010200736E 3A2DD5CDB874C3CF8A11F7CBCD026E3A2FD5B71155CBCA026E116DCBC3026E112DCF3E01CD2A65 C3D461CDCF8A326ED83E04CD2A65C3DD613A6ED84F060021447309E9C36271C34D73C3757311A2 CBCD026E115CCB3A31D5B7CA026E1164CBC3026E11E7CBCD026ECDD7883A29D5CD8F6DC3DC8811 C9CBCD026E3A30D5CDB874C3CF8A1196CBCD026E3A32D5CDB874C3CF8A118CCBCD026E3A33D5CD B874C3CF8A111BCCCD026ECDD7883A59D5CD8F6DCDDC88110DCDC3026E11BBCBCD026ECDD788CD 048CC3DC884F097EC90977C93E06CD2A65C3DD61B728297AB7201CCDCF8A7BCD6591B4280CCDCF 8A7EB7C8CD17742318F71127BAC3026E1110BACD02010200746EC3976011F9ABCD026ECD0D6EB7 28FAF5CD1774F118CCFE20300EF53E5ECD8F6DF1C640E67FC38F6DFE7F28EEDA8F6D4F3E5CCD8F 6D79E6C0CB07CB07E603C630CD8F6D79E638CB3FCB3FCB3FE607C630CD8F6D79E607C630C38F6D D5CD9068B7ED42457DB728073E20CD8F6D10F9D1C3026E1135CBC3026E7EE5CD8D743E20CD8F6D E1237ECD8D74CD7374C91193AF6F2600CD158AEB36001193AFCD026EC9F579CD8F6D10FAF1C911 44CBB72803113FCB210700C35C741144CBB7CA026E113FCBC3026E000000E5C5D522C574CDA880 CDDE7421000022C574D1C1E1C9C5D5E53A5AD5D631473A49D5D6059032C7742AA6AF010000B7ED 42F20275CD0C772201020075B4AF01000021ADAF097E21FED70977B728030C18F0793248D5AF32 ADAF2AB4AF010000B7ED42FA9675CD0C7722A6AF3A48D53247D54F060021FED7092243D52AB4AF 7DCD9D752A43D501FED7B7ED427D3248D52AA6AF22B4AF3A48D54F3AC774B9CA9675F293750100 003A47D5C5814F21FED7097EC121ADAF0977B728030C18E93A47D53248D54F060021FED7093600 C39675C31D753A48D5E1D1C1C9C5D5E54F3AA5AFB7CA18762AA6AF7DB920213AA8AF3C32A8AFFE 5EFA79763AA9AFCD7C773AA8AFC620CD7C77AF32A8AFC318763AA8AFFE012027AF32A8AF79CD9D 752A43D511FED7B7ED523AC774BDFAF3757D3247D5AF32A8AF79CD9D75C379763AA801020076AF FE02FA18763AA9AFCD7C773AA8AFC621CD7C77AF32A8AF79E67F4779E68057B7280D3AAAAFB728 073AABAFCD7C774879FE7F2804FE20300C3AACAFCD7C7779C640E67F4F2A43D53AACAFB8200277 233AA5AFB7280B3AA9AFB820053AACAF77233AAAAFB7280B3AABAFB820053AACAF772371232243 D53600E1D1C1C9229EAFC5D5E5218DD6223FD54F0600E5093600E13E0132A8AF7E234FB7CA0077 3AA5AFB728103AA9AFB9200A7ED6202332A8AF7E234FAF573AAAAFB7280B3AABAFB9200516807E 234F3AACAFB9201B7E234FE67F5F7BFE40FADD76FE60FAE176FE3F200679D640E67F4F7AB14F3A A8AF47DD21C1AFCDA58579CD5477200910F1C3917601020077E1D1C1C9CD518A3E01B718F43A31 D5B720103AA0AFFE0D20093E0A32A0AF6F2600C92AC5747CB5280A7E2322C574B72818180F119A D9CDA689200EDD21C5AFCDA58532A0AF6F2600C93EFF3226D532A0AF6F67C9E5C54F3AA0AFFE0D 20113A99BAB7280B3A31D5B7200579FE0A280A7932A0AF2A9EAFCD4181C1E1C92A43D577232243 D5C9CDCF8A3E523288D6118DD63E05CD2A65C3DD61B7280E3263DE3271D8EB36003E723288D6CD F8772100002260D52262D522BFAFAF325FD53264D5325CD53E523299BACD9E80CD0E8B1157ADCD 026ECD798FC397601195C83A5CD5B72807AF325CD51145C93A99BAB7C47F62C3976011A1C818F1 AF3235D52162DA220102007839D5CD0E8BC9CD4E803E31325AD5CDB482C3CB781827CD4E803E31 325AD53A71D83263DEAF3262DE3E52CDA981C389783E31325AD5CDB482C396601800FE53203E3A 64D53265D5AF3264D53A62DECD7180CD83803A63DE218DD6CD2F79218DD6CDEB783263DE3E59CD A981C389783A5BD5325AD53E663288D63E46CD9E80C9FE45203FCD5762C38978DD21C1AFCD877C 3E413288D63A2364FE01C011EAD92156AACD6964C3A878C9AF32236411EAD9CD8389C93E413288 D6DD21C5AFCD877CC39578AF325FD51803CDE3783A5FD53262DEAF3263DE3E4ECDA981C389783E 4ECD9E80C92A62D5232262D5C93A4AD5CD2A793A4BD5CD2A793A4ED5CD2A793A50D501020079C6 4077233A52D5CD2A793A56D577233AAAAFB728053659231803364E233A5BD577233AA9AF77233E 09C9C6207723C93271D8C5AF4732A5AFCDB4797ED6203249D5CDB479237ED620324CD5CDB47923 7ED620324DD5CDB479237EC640E67F324FD5CDB479237ED6203251D5CDB479237E3255D5CDB479 233AAAAFB728147EFE592807FE4E2005AF18053E2632ABAF32AAAFCDB479237E4F3A59D5B92802 3E31325BD5CDB479237EFE2028074F32A9AF32A5AFC1C93A71D804B8F0E1C1C9CD4E80CDB482C3 CB78FE532023CD3D7CCD2E7CC2C878CDE378218DD6CDEB783263DE3E59CDA981C389783E53CD9E 80C9FE5A201ECD3D7CCD2E7CC2C878CDE378AF32630102007ADE3E59CDA981C389783E5ACD9E80 C9FE46203BCD347CC2C878CD7180CD83803E463299BACD9E80CD4386C38978CDF877CD78803263 DE3E59CDA981C389783E743288D63A5CD5FE5AC8AF325CD5C9FE42201BCD9E80CD347CC2C878AF 3263DE3E59CDA981C389783E433288D6C9FE58C2C580CD347CC0CD567CCD707CCDCF8ACD788032 63DE3E59CDA981C389783A5FD5CD7180CD83803E643288D6C911F2BACD026E1166D5CD026E3A2C D5B7282111EAD921F2BACD6964C3DF7A2166D5CD6964C3DF7A21BEAACD6964C3DF7ACDDB80119A D9ED5395BACDA8803E643288D6C9AF322CD511EAD9CD838918E4CD4E80CDB482C3CB78FE442067 CD347C2821CD3D7C0102007BCD2E7CC2C878CDE378AF3264D53263DE3E59CDA981C389783E25CD 9E80C9CD7180CD83803A64D53265D53A63DECD0181C38978AF3264D53263DE4F3A5CD5B7280A4F 3E013263DE79328DD63E59CDA981C389783A60D5E603C03E2ECD9E80C9FE462021CD3D7CCD2E7C C2C878CDE378AF3264D53263DE3E59CDA981C389783E25CD9E80C9FE5AC2187CCD9E80CD347CC2 C878CD7180CD83803A63DEFE0120483A8DD6FE4420473A2CD5B7280C11EAD9216BAACD6964C30C 7C3AB6AFB72829CD9A85202ACD078A2805CD518A18201156AECD026E3A2CD5B7281411EAD92156 AECD6964C30C7C1806CD9A85CC8389AF325CD5CD78803263DE3E59CDA981C389783E0102007C66 3288D6DD21C1AFCD877CC9AF322CD511EAD9CD838918D5FE58C2C580CD2E7CC0AF3263DE3E59CD A981C38978C93A5FD53D18033A5FD5473A62DEB8C93AB6BA473A65D5B8380AD111CBC7CD7262C3 89783C3265D5C9ED5B93BAED5395BAAF3299BACDCF8AC9F53A99BAB7C4026EF1C9218DD63A63DE B7C84F0600093600118DD6CD026EC3CF8A2ABFAFDD4E02DD460309AFDCBB857CE603474DDD7102 DD70037CE6FC6F2600CB3DCB3DDD4E00DD460109DD7500DD7401CDC77C21000022BFAF22C9AF22 CBAFC9F53A2CD5B72846E5D5C52ACBAF7CB52815CD237D11EAD9CD6964C3167D21E1ABCD6964C3 167D2AC9AFCD237D11EAD9CD6964C3167D21E6ABCD0102007D6964C3167D21BEAACD6964C3167D CDDB80C1D1E1F1C911EAD9CD8389AF322CD5C3117DD5C51193AFD5CD158AEB3600E13E20BE2003 2318FAC1D1C9CDCF8A3E05119AD8D5CD2A65C3D461E1225DD53E0132B7AFCD31963A28A8B72009 1190A9CD026EC39760225DD5CD4381300BCDCF8A3E13CD538AC39760CDF877AF325FD53264D521 00002260D52262D522BFAF3E31325AD53E533288D63299BACD9E80CD0E8B1157ADCD026ECD798F C39760CD4E803E31325AD53A59D5325BD5218DD6CDEB783263DE3A60D53262DE3E53CDA981C390 78CDB482C39660FE592025CD347CC0CD8B803A63DE218DD6CD2F793A5BD5325AD53E463288D6CD 9E80CD8681C3B3780102007EC9FE4EC2C580CD9E80C9CD4E80AF325CD5118DD62172D801FF007E FE2F280DFE3A281CFE203818EDA00418EE362EEDA0047EFE203809FE3A2805EDA00418F2ED533F D5223BD5783263DEEB36003A5FD53262DE3E46CDA981C39078CDB482C39660FE592029CD347CC0 CD8B80CDA880CD0B81C3777E180EFEFFC2B3783E5A3288D6CD9E80C93E543288D63299BAC9FE4E C2C580CD9E80CD9480C018CD1101BBCD026E1166D5CD026E3A2CD5B7282D11EAD92101BBCD6964 C3D17E2166D5CD6964C3D17E21BEAACD6964C3D17ECDDB80180AAF322CD511EAD9CD83893E4432 88D6C9CD4E80118DD621FED73A48D5B728054F0600EDB03A48D53263DE3A5FD532620102007FDE 3E44CDA981C3B3783A60D5E6033E2ECC9E80CDB482C39660FE592045CD347CC0CD8B803A63DEFE 0120133A8DD6FE5A2005325CD51807FE582003325CD53A5CD5B72809CD9E803E5A3288D6C9CD0B 81C3547FC9FEFFC2B3783E5A3288D6CD9E80C9FE4EC2C580CD9E80CD948028DECDE378C9CD4E80 CDD0803A5CD5B728223A2CD5B7280C11EAD9216BAACD6964C307803AB6AFB728073E44328DD63E 013263DE3E5ACDA981C39078CDB482C39660FE592043CD347CC0CD8B80CD9A85CC83893A5CD5FE 5A281FCD4381381ACD8681C3B378AF325CD53E463288D6CD9E80DD21C5AFCD877CC93E423288D6 CD9E80DD21C5AFCD877CC9FE4EC2C580CD9E80CDE30102008078CD9480C018B0AF322CD511EAD9 CD8389C3917FCD4E80CDD0803E42CDA981C39078CDB482C39660FE59200DCD347CC0CD8B803E43 3288D6C9FE4EC2C580CD9E80CDE378CD9480CA3080B728E3C93AB6BA473A64D5B8380AD111F6C7 CD7262C3B378B72807F53E25CD9E80F13C3264D5C93CE63F325FD5C93A64D53265D5AF3264D5C9 2A60D5232260D5C9CD7180CD8380C378803A5FD53C473A62DEB8C94F3A99BAB7C879C38F6DAF32 26D53248D53247D532ADAF32A8AF32A0AF21FFFF22A6AF22B4AFC9FE45C2B378CD5762C3B3783A 5FD53262DEAF3263DEC9F5C5E5D52120C6E5CDD689360D233600E1D1CD6964CDF780E1C1F1C9AF 32236411EAD9C3830102008189211681CD7D76CA9564C93A26D5B7C0CDDE74C39564ED5B95BACD AD89C8CD518A3E58325CD5C9E52A9CAF77233600229CAFE1BFC9E5229CAF212781CD7D76E1C9E9 C9C5D5E506202172D8E53E20772310FC2A5DD5D1CD6089225DD5F52172D8E51166D5012000EDB0 2166D53E03012000EDB12B3600E1119AD9CD6089F13720013FE1D1C1C93EFF3227D5AF3226D532 28D5E5119AD92162DA0600CD6E89E12805FE2AC27A62C395643264DE2189D63A53D577233A5AD5 D631473A63DEC62380772306004F3A62DEC6207723CDAD823A64DE7723CDAD823A63DEB7280B3D 3263DE7E23CDAD8218EF3A5AD5FE322828300F79E6C0070781E63FC6207723C32E820102008236 00E5218AD6CD1D85E14B427A07070707E60FC620772378E60F070747790707E603B0C620772379 E63FC62077233A51D577233600233A32D5B72803360023CD4882C39660C395643A4DD54705FA59 823A4FD55FCD136E18F33A32D5B7280C1120CDCD026E118AD6CD026E3A2BD5B728211112DA2120 CDCD6964C388822189D6CD6964C38882180AAF322BD51112DACD83892189D67EB728075FCD136E 2318F53A57D5B728045FCD136EC39564814F3E008847C93A4CD5210000B728086F0E1ECD318A65 6F22BB9CCD8687CDF183C39660CDC187CDD184C3C882CDE78420F5CDD184C39660CDE78428F532 8AD64F3A5AD5D6314779D623903263DE0600CDD18401020083C39660CDE78428D73262DE328BD6 CDAD823A62DED6203262DECDD184C39660CDE78428BB326ED8328CD632D1AFCDAD823A63DE326F D8218DD6223FD53A6FD83DFA5E83326FD8CDD184C39660CDE784288E2A3FD57723223FD5CDAD82 18DECD3586C3D482CDD184C39660CDE784CADF82D6203270D83A5AD5FE322841301379E6C00707 81E63F473A70D8B82858CDE378C92A3FD53600218AD6CD1D854B427A07070707E60F573A70D8BA 20E1CDD184C39660CDE784CADF82D6203270D878E60F070747790707E603B0473A70D8B820BDCD D184C39660CDE784CADF82D6204779E63FB820A82A3FD53600233A6ED8C39564218ED72245D5CD 346EC349842A45D50102008477232245D5CDF38420ED3600233A32D5B7280C1118CDCD026E118F D7CD026E3A2BD5B728151112DA2118CDCD6964C38882218FD7CD6964C38882218ED72245D53A58 D5CDD985C395643A5CD5FE412005CDEC851864FE42200E3E5A325CD51114ADCD667CC3F783FE46 200E3E58325CD5112BADCD667CC3F783FE452022AF325CD5CDC1873E133263DE218EC9118DD64F 0600EDB03E45CDA981C39078C39760FE43200AAF325CD5CDC187C39760FE44200F3A32D5EE0132 32D5AF325CD5C3F783FE4820081157ADCD026E18EDAF325CD5C92A45D57E232245D5CDF384C295 64C9E52153D5BEE1C9E52154D518F7E52151D518F1E52152D518EBE5214FD518E5E50102008521 50D518DFE5214BD518D9E5214CD518D3E52155D518CDE52156D518C7E5C51100007EB7CA6085E5 ABE60F06004F2174850909CD63857BAE5F237AAE57E1E57ECB3FCB3FCB3FCB3FABE60F4F217485 0909CD63857BAE5F237AAE57E123C32285C1E1C9CB3ACB1BCB3ACB1BCB3ACB1BCB3ACB1BC90000 8110022183310442855206638773088489940AA58BB50CC68DD60EE78FF77E232237D5C9ED5B95 BA219AD9B7ED52C9E5F52ABFAF237CB53E01CCBB8522BFAF22C9AFF1E1C9E5DD6E00DD66010140 0009DD7500DD7401B728072ACBAF0922CBAFE1C900B7C832D885CD346EC349844F3AD885B920F3 C9119CACCD026E2A60D5CD9A6411B4ACCD026E2A6201020086D5CD9A6411CCACCD026E2ABFAFCD 9A6411E4ACCD026E2AC1AFCD9A643E4BCD8F6D11FCACCD026E2AC5AFCD9A643E4BCD8F6DC3CF8A C53AD2AF4F3AD1AFB9C1C8C395642187D53A63DECD35811172D80108007EFE2E282EFE20385D79 FE08200A7ECDD387280D365A18097ECDE28728032318DFEDA078B120D97EFE2E2807FE20383623 18F479FE0820043E581213362FEDA00103007EFE20381E79FE03200A7ECDD387280D365A18097E CDE28728032318E3EDA078B120DDD5E1363A233A29D577233600E52172D81166D5012000EDB0E1 3603223BD52172D8119AD9CD6089280E2A3BD53600119AD9CD026EC3518A219AD90128003E3AED B123223BD52B2B22010200873FD53A30D5B72865119AD92162DA0600CD6E89205811A9C8CD7262 119AD9CD83892A3FD5119AD9B7E5ED52E12006112EC8C3026E2B223FD52A3FD57EFE4238E13521 9AD9E51166D5012000EDB0D12162DA0600CD6E892008119AD9CD838918D82A3BD53600119AD9CD 026E3603119AD92162DA0600CD6789CA9564F511E4C7CD7262F1C37A62E5D5C50E002ABB9C7CB5 282722B79C0E08CDE489200A11B99CC5CDDD89C118130CFE0B20EC11C2A9CD026E21010022BB9C 0E007932C587C1D1E1C9E5D5C50E08CDEB8921000022B79CC1D1E1C9FE41D8FE5B3806FE61D8FE 7BD0BFC9FE30D8FE3A30EABFC92118D20600CD0D6EFE80281B1169BACDA6892013770102008823 04FE0D280B4F3AD0AFB779C48F6D18E6C91169BACD8389AF3265BA3E1DCD8F6D37C93A65BAB7C2 EB87FD2A8BBAFDCB126E28092118D2010050C3BA89E5D5783271D8CD238AC2B688FE08200D5F78 B728F1052B7BCD8F6D18E9FE0D2825FE18200D78B728DD3E08CD8F6D052B18F3FE1B2810FE8120 043E1B1808FE802804FE2038C004772003051810FE0D2828FE1B2824FE80282023CD8F6DFE3FC2 43883E08CD8F6D2BE5FDE13E20FDBEFF2807783D3E20C48F6D783D2008F5C17EFE3F7820013C47 7EFE1B280BCB273807CB3FF610CD8F6DD1E1C93E10C38F6D3E11C38F6D203C2A15C6712C3A17C6 BD28312215C63A97BA5F2166BA347EBB38223A68BA01020089B7281C79FE132805FE112004AF32 CFAF3A67BAB720093C3267BA1E13CD136EC9F53A2AD5FE02202FF1F5FE0A20093AD5AFFE0D2822 3E0AD532D5AF11C2D9CDAD892813CD518A11C2D9CD838911DDAACD026EAF322AD5D1F1C93E11EF 32528AC93E4EEF32528AC93E3AEF32528AC93E3BEF32528AC93E43EF32528AC93E48EF32528AC9 3E3CEF32528AC93E49EF32528AC93E05EF32528AC9C5F54F3E0618133E0FEF32528AC93E03EF32 528AC9C5F54F3E04EFC132528A78C1C93E09EF32528AC93E64EF32528AC93E4CEF32528AC93E21 EF32528AC93E13EF32528AC93E1DEF32528AC93E1CEF32528AC93E1EEF32528AC93E20EF32528A C93E10EF32528AC90102008A3E65EF32528AC93E39EF32528AC93E60EF32528AC93E61EF32528A C93E08EF32528AC93E01EF32528AC93E19EF32528AC93E5BEF32528AC9C5F54F3E02C3B2893E52 EF32528AC96F26003E16EF32528AC93E00C5F5FD2A8BBAFDCB02B6FDCB02BEFDCB12B6F6C04FCD CF8A3E1AC3B289FD21E188ED5B8FBA0E04CD9189110000CD408A204122C98CE5DDE1DD360646DD 36074F3E02DD770021C08CDD7501DD7402110000CD408A201D227A8CE5DDE1DD360646DD360749 3E01DD770021718CDD7501DD7402C91189ABCD026EC3EE61F53E0DCD8F6DF1C93E06CD2A65C3DD 61B7CAD4617AB7201F4BCDCF892019C530061181AACD026E119BAACD026EC179C6300102008B32 29D5C397603E20CD538AC39760F53A17C63215C6AF3266BA32CFAF3267BAF1C93E051173AECD2A 65C3DD61B7200B3A29D53273AE3E0D3274AECDCF8ACDCF8AFD2A8BBAFD7E1BE60F2167AEFE0228 03216BAE116FAE010400D5EDB0E1CD2A8AC397603E05119AD8D5CD2A65C3DD61B72858CDCF8AE1 225DD5AF32B7AFCD31963A28A8B72844225DD5CD4381383C1172D80600218DD6CD6E892809FE2A 2805CD518A1826219AD90120003E03EDB12B360011B3AACD026E119AD9CD026ECDCF8A1172D8CD 078A28C118D5C39760CD008AFD7E0AE6F8FD770A062ECDF989FD7E0AE607C01169BA21BD9C010B 00EDB01169BA2115C30600CD6E892803FE2AC03E010102008C3265BAC93A34D5FE20300AF5113C C9CD026EF1F640CD8F6DC93E0FCD8F6D2100260606CD9F89210EBB0605CD9F89210026110EBB01 8007EDB03E0ECD8F6DC9CD198C0604CD9F892210C32A0EC30603CD9F893E0ECD8F6DC9CD198C06 04CD9F89220EC32A10C30603CD9F893E0ECD8F6DC9180CC08C04494E50240000000000CD126C28 14CD0D6EB728F5FE8020043E1CB7C95FCD136E18E74F3A68BAB7200979FE1128DBFE1328D73A7E 8CFE0D79200E3A31D5B7792007FE0A327E8C28C1BFC9180BD38C044F5554240000000059CD136E 79BFC93E01116BCFCD2A65C3D4614FCDCF8A060021EF8C093E4732BCAFE9C39C8EC3568EC34C8E C3608EC36A8EC3200102008D8FC37E8EC3928EC3A68EC3888EC3B08EC3BA8EC3C48EC3D08EC3DC 8EC3E88EC3F48EC3008FC30C8FC3748EC3168F1187D5060032B7BAFE4A2804FE56200479121304 0E00ED53B8AFED43BAAFCD528F3E31325AD5AF3262DE3E493288D6CDF8772100002260D52262D5 AF3299BA325FD53264D5325CD5CD0E8BCD798FC39760CD4E803A5FD53262DE21FED7118DD63ABC AFFE432801133AB8BAB728054F0600EDB04F3ABCAFFE4328093AB7BA328DD60C3E47F5793263DE 3E31325AD53A59D5325BD5F1CDA981C39078CDB482C39660FE5320263A63DE218DD6CD2F79218D D6CDEB783263DE3E59CDA981C390783A5BD5325AD53E663288D6C9FE58201ACD567C0102008ECD 707CCD8B803263DE3E59CDA981C390783E643288D6C9FE59200CCDCF8ACD707C3E433288D6C9FE 4EC8FE452009CD5762CDCF8AC397601141ADCD026EAF3263DE3E45CDA981C39078C397603E0132 BDAF3E44C32E8D3E0132BDAF3E45C32E8D3E0132BDAF3E55C32E8D3E0132BDAF3E48C32E8D3E02 32BDAF3E50C32E8D3E0132BDAF3E50C32E8D3E0132BDAF3E54C32E8D3E0232BDAF3E57C32E8D3E 0232BDAF3E43C32E8D3E0232BDAF3E52C32E8D3E0232BDAF3E4BC32E8D3E0232BDAF3E4DC32E8D 0E533E0232BDAF3E56C32E8D0E513E0232BDAF3E56C32E8D0E633E0132BDAF3E4AC32E8D0E733E 0132BDAF3E4AC32E8D0E2B3E0132BDAF3E4AC32E8D0102008F0E2D3E0132BDAF3E4AC32E8D3E03 32BDAF3E6CC32E8D3E0132BDAF3E51C32E8D11FED73E05CD2A65C3D4613271D83E04CD2A65C3DD 613A71D832B8BA4F060021FED70936003E0132BDAF3E4332BCAFC34F8D3E05118DD6CD2A65C3D4 61CD9290C3708F2187D5CDC8743A48D532B8BAC9117AACCD026EC397603A88D6FE442006CDE17E C3798FFE462006CD0A7EC3798FFE542006CD9C7EC3798FFE5A2006CD737FC3798FFE532006CDAD 7DC3798FFE422006CD1480C3798FFE432006CDD977C3798FFE412006CDF377C3798FFE642006CD EB7AC3798FFE662006CDBD79C3798FFE742006CD9C7AC3798FFE522006CD0678C3798FFE722006 CD1678C3798FFE47010200902006CD7F8DC3798FFE492006CD1890C3798FCDF377C39760CD4E80 3E31325AD53A59D5325BD5218DD6CDEB783263DE3A5FD53262DE3E49CDA981C39078CDB482C396 60FE59C26490CD347CC0CD8B803A63DE218DD6CD2F793A5BD5325AD53E473288D6C9FE4E2004CD E378C9FE45C290783E503249D5AF324DD5324FD53E0D3251D53E31325AD53E233255D53E473288 D6C9218DD6ED5BB8AFED4BBAAFD5C5133ABDAF47F132BDAF7EFE20202123BE28FC10060412130C 18EF79C620E377E1D5130E003ABDAF3C32BDAF20DCD1C9380F0CEDA00C3ABDAF3C32BDAF20CBD1 C9E179C62077AF123ABDAF32B8BAB7CA95643CFE5CF032B8BAC395642AFCB97EB7280102009106 2322FCB9BFC921FEB922FCB9CDD86DC03202BACD6591B420E33A02BABFC92203BA3205BAF57832 01BAF1CD6591B4C47B913A01BAB7C821FBB9ED5BFAB1B7ED524F0600B7ED42300711BAABCD026E C92A03BAD5EDB0EB36002322FAB1D12A06BA732372C921F8AF4F0600CB01300104CB81092206BA 7E23666FC92A06BA5EAF77235677ED5308BA626BEDB1E5B7ED52220ABA2AFAB1C1B7ED42C5E5C1 E178B12802EDB0ED53FAB121F8AF0600C54E23462B78B1281CE52A08BAB7ED42F2D1916069ED4B 0ABAB7ED424D44E17123701802E12323C110D6C93E05118DD6ED53CDAFCD2A65C3DD613E0132D3 9DCD1D96206DCDD994C293945F3ACB9DB72806AF3201020092CB9D18E8CD136E3A2AD5B77BC420 89FE2038D93ACF9DB728D37BF5CD126C2817CD0D6EB728F5FE80CA7694FE1BCA7F94FE81CA7F94 18E45F3AD4AFB77BC49E6D3A2AD5B77BC42089CD3C945FF1CD3C94BB28997BFE2038941166A8C3 6E94AF32D39DC397603E05118DD6ED53CDAFCD2A65C3DD613E0132D49D21019A0600CD1D96C2A5 92CDD994C293945F3ACB9DB72806AF32CB9D18E773230420E2119CA8CD026EC3BE943600783201 9BAF0E01CD649416024A3A019BB9FAE2924A0DCD55945F1C1D28144BCD5094474A0DCD5094B828 074BCD55945F18E87B3C4ACD64941418D11E003ACA9DB728404FAF32CA9D7932CC9D4F3AD3AFB7 280479CD9E6D3A2A01020093D5B779C420891C1C1D28194B0DCD5094CD3C944F3ACC9DCD3C94B9 28074BCD55945F18E33A019BBB2822CD126C28C1CD0D6EB728F5FE80CA7694FE1BCA7F94FE81CA 7F94D55FCD136ED118DEAF32D49DC397603E05118DD6ED53CDAFCD2A65C3DD613E0132D59D2104 9B22029BCD1D96C28A93CDD994C293945F3ACB9DB72806AF32CB9D18E7732318E37723360001B8 0BCD126C2849C5CD0D6EB7281DFE80C1CA7694FE1BCA7F94FE81CA7F94C55FCD136E3A2AD5B77B C42089C10B78B120D121049B7EFE0D2006237E2BB728C023E55FCD136E3A2AD5B77BC42089E118 E432CA9DAF32D59DC397603E06CD2A65C3DD61B720031101006B620E1ECD318A656F0102009422 B79C0E08CDE4892014FD2A8BBAFD7E0AE6F8FD770A11B59CCDDD8918140CFE0B20E211EAA9CD02 6E01FFFFCDF989C397602AB79C7CB520F9C39760F53ACD9DB7280BF1FE61F8FE7BF0E65F1801F1 C921019A1803210199C50600097EC1C921019A1803210199C506000977C1C9CD026E1803CD518A 11B9A8CD026EC3BE94118EA8CD026E2A1AD336001118D2CD026EC397603AD19DB7280811CEA8CD 026E181D3AD29DB7280811EEA8CD026E180F3AD69DB7CA9760110EA9CD026E18003AD09DB7CA97 603A65BAB7CA97601169BACD8389AF3265BAC39760E5C5D5FE5C2041AF473C32D19DCD1D96C2D6 95FE30FA1895FE3AF21895FE30FA0F95FE3AF20F9501020095D630CB20CB20CB208047CD1D9628 E72ACDAF2B22CDAF7778F5AF32D19DF1C3D595FE5E20163E0132D29DCD1D96C2D695D640F5AF32 D29DF1C3D595FE3CC2D5953E0132D69D21A99CCD1D96C2D695FE3E2807CD4494772318EF36FF21 049C462311A99C1ABE2022237E13FE303806FE5B300218EF4F1AFEFF200F79FEFACAA395F5AF32 D69DF1C3D5954F7EFE2A20067932AF9C18D23EFEC5010000EDB1C110C0C3DA953AAF9CD6306F26 000E1ECD318A656F22B79CFD2A8BBAFD7E0AE6F8FD770A0E0811B59CCDDD892AB79C7CB520F93E 0132CB9DBFD1C1E1C9114AA8CD026EAF3C18F2E5F5FDE5FD2A8BBA2AB79C2B22B79C7CB5200CFD CB0A86FDE1F1E1CD01020096F289C9FDCB0A46280F21000022B79C26322B7CB520FB18DFFDE1F1 E1C9E52ACDAF7E2322CDAFFE0D2803BFE1C9FE0EE1C922D79D2126A02226A8AF3228A82AD79D01 0000ED4346A8ED4348A8AF3242A83239A83E20BE20032318FA1131A8CD598928091141AACD026E C397603A39A8E6A020F03A42A8E6A020E93E20BE20032318FA062011269F7EFE213808CD449412 132310F3AF127EFE213007FE0D28032318F422D79D3E209032039FCAA6973E0132049F1BEB7EFE 2F2002360021269F3A039F4F0600092B0D281B2B0D28177EFE3A20123600237E21039F3535D630 4FAF32049F1802AF4FC5CDCF89C294972129A811059F010800EDB0C1C579C630320D010200979F 32E29D3E0D320E9F21E39D060011059FCD6E89C2AF9711059FCD7C89CD7C8921E39D11059FCD75 89C27B97060821E39DC5CB66283CCB7E20383A46A8B72004CB76202E3A48A8B72004CB5E202411 269F3E0132D99DCDE8982804AF32D99DCDBA97200ECD70983AD99DB72005C1C1C33E9601200009 C110B818A5FE1C280CCD518A11059FCD8389C3976011059FCD8389C2B497C10C3E08B9CA3E963A 049FB7C2E796C33E962A26A8360D2126A0C9CD518A18E0CD518AC39760C5E5D50105000911E39E 01300B7E23FE20280C2B78FE0320043E2F1213EDA010ECAF12D1D521E39E7EB7287F1AB7287BED 53DA9D22DC9D21000022DE9D22E09D2ADC9D7EB7280102009813ED5BDA9D1ABE200B2313ED53DA 9D22DC9D18E67EB7200DED5BDA9D1AB72005BFD1E1C1C9ED5BDA9D1AFE24200B231322DC9DED53 DA9D1834FE2A200E13ED53DA9DED53DE9D22E09D18222AE09D7CB528137EB7280F2322DC9D22E0 9D2ADE9D22DA9D18083E01FE00D1E1C1C9C3FA97D5E5C521E39EED5B26A8D57EB72817EDA0E5D5 E10126A8B7ED42E120EE11A2A9CD026EC39760D5E10122A8B7ED42200911A2A9CD026EC397603E 3A12133AE29D12133E2012133E0012ED5326A82128A87EF534B7200C3AB7AFB728061180A9CD02 6EF1FEFF28C9D13AB7AFB72806CD026ECDCF8AC1E1D1C9E5D5EB7EB7280BFE24280BFE2A280723 18F13CD1E1C9BF1801030099FA0105019B00000001A7049C2341434B06FE42454C07FE425308FE 43414E18FE43520DFE44433111FE44433212FE44433313FE44433414FE44454C7FFE444C4510FE 444C592AFAFE454D19FE454E5105FE454F5404FE4553431BFE45544217FE4553431BFE46460CFE 46531CFE47531DFE485409FE4C460AFE4E414B15FE4E554C00FE52531EFE53490FFE534F0EFE53 4F4801FE53504120FE53545802FE5355421AFE53594E16FE56531FFE56541FFE000115B59CE495 0000776E00004B45524D49542F494E490D011BCA9D000000000000010000000000000000000000 000000000000300125039F00004449522F5359533A300D00000000000000000000000000000000 00000000000000010226A826A0004449522F5359533A805653595354454D0046A855494E564953 0048A800000000000D42616420636F646520696E73696465206F66203C2E2E2E3E2773000D486F 737420646964206E6F74206563686F206C617374206368617261637465722073656E740D000D49 676E6F72696E67203D3E20000D537472696E6720746F6F2062696720666F722062756666657221 0D000D4F7065726174696F6E2061626F72746564210D000D4D697373696E672063686172616374 657220666F6C6C6F77696E67205C0D000D4D697373696E672063686172616374657220666F6C6C 6F77696E67205E0D000D4D697373696E67203E20696E203C2E2E2E3E2073657175010226A9656E 63650D000D10456E7465722061207465787420737472696E67110D000D10456E74657220612066 696C652073706563696669636174696F6E21110D000D10456E746572206120446563696D616C20 6E756D62657221110D0053656E64696E672066696C65733A0D00104E6F2066696C657320666F75 6E64110D0010546F6F206D616E792066696C65732C206F7574206F66207370616365110D000D10 4E6F207461736B20736C6F747320617661696C61626C6520666F722074696D656F7574110D000D 104E6F207461736B20736C6F747320617661696C61626C6520666F722064656C61792C20757369 6E672031207365636F6E64110D000D1043616E27010226AA74206D6F7665204C4F572420746F20 6E65772076616C7565110D000D42616420706172616D65746572206C6973740D005472616E7361 6374696F6E2061626F727465640D005472616E73616374696F6E2063616E63656C65640D000D44 726976652069732077726974652070726F746563746564000D44656661756C7420647269766520 6368616E6765640D0052656D6F76696E673A200020202054696D653A20004C6F672066696C6520 492F4F206572726F722E20204C6F672066696C6520434C4F534544210D0020202020000D545253 2D3830204D6F64656C203428702920545253444F5320362E32202D204B45524D4954202D205665 7273696F6E2035010226AB2E320D427920477265676720576F6E6465726C790D0D547970652061 203F20666F722068656C7020617420616E792074696D652E2E2E2E0D000D4E6F202A434C204443 42210D000D4E6F202A534F20444342210D000D4E6F202A534920444342210D000D43616E206E6F 742066696E6420612044434220666F7220746865202A4649206F72202A464F2064657669636573 210D000D4E6F7420656E6F756768207370616365206C65667420666F7220646566696E6974696F 6E0D004B202B2000206279746573207472616E7366657265642E000D5072657373206B65797374 726F6B6520796F75206465736972653A20000D456E74657220646566696E697469010226AC6F6E 20737472696E672C20656E642077697468203C425245414B3E2028323535206368617261637465 7273204D4158290D000D52656D61696E696E67206B657920646566696E6974696F6E2073706163 653A20000D537472696E6720746F6F206C6F6E6720666F72206F6E65207061636B6574210D000D 4E756D626572206F66207061636B65747320203D3E20000D4E756D626572206F66207265747269 657320203D3E20000D4279746573207472616E7366657265642020203D3E20000D4B6279746573 207265636569766564202020203D3E20000D4B6279746573207472616E736D6974746564203D3E 200020105B43616E63656C6C696E672062617463010226AD685D11200020105B43616E63656C6C 696E672066696C655D1120000D556E6B6E6F776E207061636B657420747970650D000D20202020 204354524C2D46203D3E2043616E63656C2066696C652020202020202020202020204354524C2D 42203D3E2043616E63656C2042617463680D20202020204354524C2D43203D3E20517569742070 726F746F636F6C202020202020202020204354524C2D41203D3E205472616E7366657220737461 7475730D20202020204354524C2D44203D3E20546F67676C6520646562756767696E6720202020 2020204354524C2D48203D3E2054686973206D6573736167650D20202020204354524C2D45203D 3E2053656E6420014B26AE6572726F722C207175697420202020202020454E54455220203D3E20 526573656E64206C617374207061636B65740D000720105B4469736361726465645D1120004341 542044495220012273AF5452414E532F4C4F470D53455353494F4E2F4C4F470D44454255472F4C 4F470D011699AF00000000000000000000004E000000007E0126230102B4AF0000000100000000 0000000000000000000000000000000000000000000000000000000102030405060718091A0B0C 1D0000101112131415161718191A1B1C1D1E1F2021000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000102B4B0000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 00014AB4B100000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000FCB101 43FCB9FEB90000000000000000000000000000000000000D56616C7565206F7574206F66207261 6E676521210D000D4E6F20646566696E6974696F6E2065786973747300010665BA000000010187 89BA0000000000010000000000000000B4500108204F6E65206F662074686520666F6C6C6F7769 6E672E2E2E0D000007000000000D104C6F6766696C6520697320616C7265616479204F50454E21 110D000D104C6F6766696C65206973206E6F74204F50454E21110D00000D526563656976696E67 203D3E20000D53656E64696E67203D3E200001090EC300000000000030010D15C615C515C55345 54434F4D20010220C70E10114B45524D495420342870293E000D000D10556E7265636F676E697A 656420636F6D6D616E64110D000D10496C6C6567616C20636861726163746572110D000D104E6F 7420636F6E6669726D6564110D00556E61626C6520746F207265636569766520696E6974696174 650D00556E61626C6520746F20726563656976652066696C65206E616D650D00556E61626C6520 746F207265636569766520656E64206F662066696C650D00556E61626C6520746F207265636569 766520646174610D000D53797374656D20444F53206572726F720D004E6F2061636B6E6F776C65 6467656D656E742066726F6D2074686520686F73740D000D556E61626C6520010220C8746F2066 696E642066696C650D00556E61626C6520746F2072656E616D652066696C65000D556E61626C65 20746F2074656C6C20686F73742074686174207468652073657373696F6E2069732066696E6973 686564000D556E61626C6520746F2074656C6C20686F737420746F206C6F676F757400070D436F 6D706C6574656400074661696C65640052656E616D696E672066696C65203D3E20000D3C436C6F 73696E6720746865206C6F672066696C653E000D3C436F6E6E656374656420746F2072656D6F74 6520686F73742C207479706520004320746F2072657475726E3E0D3C434C4541523E2069732043 6F6E74726F6C2D5F0D000D3C436F6E6E6563010220C974696F6E20636C6F7365642C206261636B 206174206D6963726F3E00436F6E74726F6C2D00070D496E746572727570746564000D46696C65 204B494C4C4544000D10436F6E6669726D2077697468203C454E5445523E2C2063616E63656C20 77697468203C425245414B3E110D005472616E736665722061626F727465642E2E2E0D54797065 20746865206E657720657363617065206368617261637465723A2000100D110D0D202020203F20 3D202054686973206D6573736167650D2020202030203D2020287A65726F29205472616E736D69 742061204E554C4C0D2020202042203D202053656E64206D6F64656D20627265616B0D20202020 43203D2020010220CA436C6F73652074686520636F6E6E656374696F6E0D2020202051203D2020 51756974206C6F6767696E672073657373696F6E0D2020202052203D2020526573756D65206C6F 6767696E672073657373696F6E0D0D547970652074686520657363617065206368617261637465 7220616761696E20746F2073656E6420697420746F2074686520686F73742E100D110020202020 202020202020202020202020202020202020201053656E6411202010526563656976651120207C 20200010496E7075742073657474696E6773112020202020202020202020202020202020202020 202020207C202000104F75747075742073657474696E677311202020202020010220CB20202020 202020202020202020202020207C2020002020202020207C202000104F4E1100104F4646110010 584F4E2D584F46461100104E4F4E45110010415343494911001042494E41525911001044554D42 110010444953434152441100104B454550110042656C6C3A20005072696E7465723A2000446562 756767696E673A200046696C6520747970653A20004C6F63616C206563686F3A20004573636170 6520636861723A200046696C65207761726E696E673A2000466C6F7720636F6E74726F6C3A2000 44656661756C742064726976653A2000456D756C6174696F6E20747970653A200046696C652064 6973706F736974696F6E3A2000426C6F636B010220CC20636865636B20747970653A2000446973 706C61792054414B452066696C653A20004569676874206269742071756F74696E673A2000456E 642D6F662D6C696E653A2020005475726E2061726F756E643A2020005061642063686172616374 65723A202000436F6E74726F6C2071756F74653A20200054696D65206F75742076616C75653A20 200050616464696E67204C656E6774683A20200053746172742D6F662D7061636B65743A202000 446973706C617920696E7075743A20200049676E6F726520636173653A202000446973706C6179 206F75747075743A2020004D61746368206563686F3A2020002D63686172616374657200525061 636B3D3E00010220CD535061636B3D3E001C1F001E090103425945002121000143000606010543 4C454152003F3F0105434C4F53450042420107434F4E4E45435400060601034449520024240001 4500030301044543484F004545010445584954000303010646494E495348001B1B010347455400 0C0C0105494E50555400333301044B494C4C00272700014C002A2A01054C4F43414C002A2A0103 4C4F4700090901064C4F474F5554001E1E01064F55545055540036360105504155534500393901 0550554C5345003C3C000152000C0C010752454345495645000C0C010652454D4F544500000000 0153000F0F010453454E44000F0F01035345540012120106534554434F4D00010220CE2D2D0104 53484F570015150106535441545553001818010454414B4500303012130103414C4C0011130104 42454C4C001B1B0110424C4F434B2D434845434B2D54595045000C0C0109444542554747494E47 001515010C44454641554C542D4449534B001818011145494748542D4249542D51554F54494E47 0006060109454D554C4154494F4E000F0F0106455343415045000000010446494C45000909010C 464C4F572D434F4E54524F4C0027270105494E50555400292901034B4559002424010A4C4F4341 4C2D4543484F00030301064F5554505554002D2D01075052494E54455200121201075245434549 5645001E1E010453454E44002121010C5441010220CF4B452D444953504C4159003030030D010B 444953504F534954494F4E00000001045459504500030301075741524E494E4700060602090107 4449534341524400010101044B45455000000015100109434C4F53452D4C4F47002A2A0104434F 5059001E1E0103435744000000010644454C455445000303010344495200060601044449534B00 0909010448454C50000C0C0104484F5354000F0F01064B45524D495400121201054C4F47494E00 363601074D455353414745002121010750524F4752414D003939010E51554552592D5641524941 424C45002727010652454E414D45001818010853454E442D4C4F47002D2D010D5345525645522D 5354415455010220D053003C3C010C5345542D5641524941424C45002424010953544152542D4C 4F47003030010853544F502D4C4F47003333010454595045001B1B010357484F00151502060104 44554D4200030301044E4F4E45000000030D01054445425547000101010753455353494F4E0000 00010B5452414E53414354494F4E000202020C010A494E5055542D504F52540000000106534352 45454E000303020A01044E4F4E450000000108584F4E2D584F46460001010711010B454E442D4F 462D4C494E45000C0C01085041442D43484152000000010750414444494E47000303010F51554F 54452D434841524143544552000F0F010F53544152542D4F462D5041434B4501FA20D154000606 010854494D452D4F555400090901095455524E2D43484152001212020B0109484F53542D454348 4F0000000107444953504C4159000303020D010B434153452D49474E4F52450000000107444953 504C41590003030208010642494E41525900010101054153434949000000030801013100313101 0132003232010133003333040500024E4F00000001024F4E00010101034F464600000000035945 530001010D50726F6772616D206572726F722C20496E76616C696420434F4D4E442063616C6C00 0D416D626967756F7573000D496C6C6567616C20696E7075742066696C6573706563000D000000 00000000000000000000010E18D3000000000000000000000000014424D5000000000030000000 000000000000001F00000000000000000000000062DB000000000000205E0F0A000000000D0D01 0123230000313131009AD800000000000000010388D60001066ED8000000000202006000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000 ***** 854 ***** <<< m4mit.hlp >>> TRS-80 Model 4(p) KERMIT version 5.2 for TRSDOS 6.x, January 1986: An advanced Kermit derived from TRS-80 Kermit, which was in turn derived from CP/M-80 Kermit. Sum bugs have been fixed, as well as the addition of wild cards in the SEND command. The SET command was modified with regard to the FILE-TYPE, and FILE-DISPOSITION options. These have become sub commands to a new SET FILE command. The equivalent functions are now accessed via SET FILE TYPE, and SET FILE DISPOSITION. The following files are provided in the Kermit distribution: Assembler source, consisting of the following modules: M4ADD.ASM M4H191.ASM M4KEY.ASM M4MIT.ASM M4SEND.ASM M4STR.ASM M4CMD.ASM M4H192.ASM M4LOG.ASM M4PKT.ASM M4SET.ASM M4TERM.ASM M4GET.ASM M4H19S.ASM M4MAC.ASM M4RMT.ASM M4SHOW.ASM M4WILD.ASM M4XFER.ASM Documentation: M4MIT.HEX -- Hexified object module for KERMIT executable M4H19.HEX -- Hexified object module for H19 filter M4H19S.HEX -- Hexified object module for SETH19 program M4MIT.NR -- Nroff source for M4MIT.DOC M4MIT.DOC -- Documentation M4MIT.HLP -- This file M4BOO.BAS -- Basic program for converting the hex files to runnable programs Here is a list of all of the command line commands that are currently functional: BYE CLEAR INPUT-PORT SCREEN CLOSE SESSION-LOG CONNECT DIR partspec EXIT FINISH GET filespec INPUT control string KILL filespec LOCAL TRSDOS command LOG filespec LOGOUT OUTPUT control string PAUSE number of seconds PULSE control string REMOTE command CLOSE-LOG COPY CWD DELETE DIR DISK HELP HOST KERMIT LOGIN MESSAGE PROGRAM QUERY-VARIABLE RENAME SEND-LOG SET-VARIABLE START-LOG STOP-LOG TYPE WHO SEND filespec(s) SET parameter [value(s)] ... BELL ON (or OFF) BLOCK-CHECK-TYPE 1 2 3 DEBUGGING OFF (or ON) DEFAULT-DISK (drive number) EIGHT-BIT-QUOTING ON (or OFF) EMULATION NONE (or DUMB) ESCAPE FILE DISPOSITION KEEP (or DISCARD) TYPE (ASCII or BINARY) FLOW-CONTROL XON/XOFF (or NONE) INPUT CASE-IGNORE OFF (or ON) DISPLAY OFF (or ON) KEY string LOCAL-ECHO OFF (or ON) OUTPUT HOST-ECHO ON (or OFF) DISPLAY OFF (or ON) PRINTER OFF (or ON) RECEIVE END-OF-LINE ascii code PAD-CHAR ascii code PADDING decimal number QUOTE-CHARACTER ascii code START-OF-PACKET ascii code TIME-OUT decimal number TURN-CHAR SEND END-OF-LINE ascii code PAD-CHAR ascii code PADDING decimal number QUOTE-CHARACTER ascii code START-OF-PACKET ascii code TIME-OUT decimal number TURN-CHAR TAKE-DISPLAY OFF (or ON) WARNING ON (or OFF) SETCOM SHOW STATUS TAKE filespec <<< m4mit.nr >>> .po 13 .na .nh .LP .ND .NP .tl ''\fITRS-80 Model 4(p) KERMIT: Version 5.2\fR'' .sp .tl ''\fIFor Use Under TRSDOS 6.1 or Later\fR'' .sp 2 .IP \fIProgram\ by:\fR 19 Gregg Wonderly Oklahoma State University, (gregg@okstate) rewritten from the original Model-4 KERMIT which was derived from the TRS-80 KERMIT done by Stan Barber, Rice University who modified the CP/M-80 version by Bill Catchings and others. .IP \fILanguage:\fR 19 Z80 Assembler, compatible with M80 and EDAS from Misosys .IP \fIVersion:\fR 19 5.2 .IP \fIDate:\fR 19 Wed Oct 22 10:17:07 CDT 1986 .IP \fIDocumentation\ by:\fR 19 Gregg Wonderly .sp 2 .NH Summary of TRSDOS 6.1 .sp .PP \fITRSDOS\fR (The Radio Shack Disk Operating System) has a large library of built in commands dealing with files, directory maintenance, device I/O, etc. Programs are also used for some functions on some \fITRSDOS\fR-based DOS's. Model 4(p) KERMIT gives you access to all of the library commands of \fITRSDOS\fR versions 6.x via the LOCAL command. Issue the \fILIBRARY\fR command at \fITRSDOS Ready\fR to obtain a list. .PP \fITRSDOS\fR file specifications can be represented as a sequence of characters of the form .RS .sp FILESPEC/EXT.PASSWORD:D .sp .RE .IP \fIFILESPEC\fR 11 is the filename up to eight characters. .IP \fIEXT\fR is the file type, up to three characters. .IP \fIPASSWORD\fR is the password for that file, up to eight characters. .IP \fID\fR is a numerical drive specification (0-7). .PP File names, file types and passwords may contain letters and numbers, but the first character in each must be a letter. No special characters or spaces are allowed. All fields are optional except the filespec. Any field added must be preceded by its special delimiter '/' for file type, '.' for passwords and ':' for drive specifications. Upper and lower case characters are equivalent. .NH TRSDOS Commands of Interest .sp .NH 2 CAT PARTSPEC:D (OTHER OPTIONS) .sp .RS This command is specific to \fITRSDOS\fR version 6.2 and later. It displays only the names of visible files on the drive specified, or all drives if no \fIpartspec\fR is given. \fI(other options)\fR allows different formats and invisible as well as system files to be selected. See the \fITRSDOS\fR manual for specifics .RE .NH 2 DIR PARTSPEC:D (OTHER OPTIONS) .sp .RS DIR is common to all version of TRSDOS. Versions after 6.1 replaced the DIR command with CAT, and changed the DIR command so that always produces a long listing. .RE .NH 2 FREE :D .sp .RS Gives statistics on disk usage. If D is present, it indicates a drive number, and only the statistics for the specified disk will be shown. .RE .NH 2 REMOVE/PURGE FILESPEC (PARAMETERS) .sp .RS Remove the file(s) given by FILESPEC from the directory and frees the space allocated to the file for reassignment. Purge allows PARTSPECs that specify groups of files. With no PARAMETERS, PURGE prompts before deleting any file. REMOVE requires a full filespec as the name of the file to remove. REMOVE allows more than one filespec to be given on the command line. .RE .NH 2 LIST FILESPEC (PARAMETERS) .sp .RS Lists the file on the display. Parameters are described in the \fITRSDOS\fR manual in detail. \fI(HEX)\fR is sometimes useful to display the hexidecimal values of the characters in a file. .RE .NH 2 RENAME oldfile newfile .sp .RS Changes the name of oldfile to newfile, provided that newfile is a unique file name on that disk. .RE .NH Copying Disks and Files: .RS .NH 2 COPY file1 file2 .sp .RS Copies file1 and name the copy file2. If file2 exists, it will be replaced. .RE .NH 2 BACKUP :D :E .sp .RS Makes a copy of the disk in drive D on the the disk in drive E. .RE .NH 2 FORMAT :D .sp .RS Formats the disk in drive D. The disk will be ready for any normal read or write operation following successful completion of this operation. This operation must be performed before use of a blank disk. Reformatting a previously formatted disk will cause all previously stored information to be lost. .RE .RE .NH Transfers without the KERMIT Protocol .PP Model 4(p) KERMIT adds 2 logical devices to the already resident devices. These devices are used to access the communications port. These devices, *FI (File Input) and *FO (File Output), can be used as the source, and destination of a copy command, respectively. They make use of the status of the SET FLOW-CONTROL parameter, to send and receive data using the communications port. For instance, say you are communicating with a computer that does not have KERMIT. Say you also wish to transfer a file to this computer to do some further processing. The normal method involves starting a program on the remote computer to collect the data into a file on that system. On a VAX/VMS system, you might use the CREATE command to capture the file. The following \fIKERMIT\fR commands will accomplish the transmition of a file in this case. .sp .RS OUTPUT CREATE MYPROG.DAT .br LOCAL COPY PROG/DAT *FO .RE .sp The KERMIT command, OUTPUT, will send the string "CREATE MYPROG.DAT" to the host. Let's say for now that this is sufficient to cause all future characters sent to the host to be placed into the file MYPROG.DAT on that system. The KERMIT command LOCAL is then used to invoke the \fITRSDOS\fR library command COPY. COPY will copy the contents of the file "PROG/DAT" to the *FO device. The driver for this device is part of the KERMIT program, and will take care of transmitting the data out of the communications port to the HOST. If the HOST sends XOFF because DATA is arriving TOO fast, then the XON/XOFF option to the \fIKERMIT\fR command, SET FLOW-CONTROL, will allow the transfer to pause while the HOST catches up. You may wish to collect the contents of a file that is on another computer. If particular computer does not have \fIKERMIT\fR, you can use a series of commands similar to those listed below to retrieve the file. It should be noted that the \fISESSION-LOG\fR can also be used to trap the contents of a file. For that very reason, this is only one of several possible ways to get a file from another computer that does not have \fIKERMIT\fR. .sp .RS OUTPUT TYPE MYPROG.DAT .br INPUT TYPE MYPROG.DAT .br LOCAL COPY *FI MYPROG/DAT:1 .RE .PP It may help to clarify the use of the \fIOUTPUT\fR command, and the corresponding \fIINPUT\fR command. If you use the \fIKERMIT\fR command \fICONNECT\fR to enter terminal mode, and then proceed to tell the host to type out a file, it may start sending data before you can escape back, and type the \fICOPY\fR command. This means that some of the data would be lost. With \fIFLOW-CONTROL\fR set to \fIXON/XOFF,\fR and the remote host recognizing this fact, the previous commands would not allow any data to be lost. The use of \fIINPUT\fR is only to remove the characters ECHOed by the host from the input buffer (The TEXT of the command "TYPE MYPROG.DAT"). If you are communicating with a half-duplex system in which \fIModel (4)p KERMIT\fR is echoing the characters typed on the keyboard, then the \fIINPUT\fR command need not be used. .sp 3 .NH Control of File Transfers Using the KERMIT Protocol .sp .PP During the transfer of a file using either \fISEND\fR, or \fIGET\fR and possibly during the use of the \fIREMOTE\fR command, protocol operations may need to be aborted, or altered. Several key strokes allow the user to control the protocol operations. These are listed below, and are listed on the screen after issuing either the \fISEND\fR or \fIGET\fR commands. The operation of the \fIREMOTE\fR command is purposefully silent. The key strokes are available to the user during \fIREMOTE\fR commands, for added flexibility. This allows the user to cancel commands like \fIREMOTE TYPE\fR that may otherwise cause large amounts of data to be displayed for an extended amount of time. The valid key strokes are: .sp .IP \fIControl-F\fR 15 During data transfers using the \fIKERMIT\fR protocol, \fIControl-F\fR will terminate the current transaction. If there are more files to transfer, the next transaction will be started. \fIModel 4(p) KERMIT\fR will send a signal to the remote \fIKERMIT\fR telling it to stop sending packets for the current transaction. If the remote \fIKERMIT\fR understands this signal (not all implementations of \fIKERMIT\fR do), it will comply, otherwise the transaction will continue. .IP \fIControl-B\fR Like \fIControl-F\fR, except that if a group of files is being processed this will stop the entire group. If only a single file is being \fISENT\fR or \fIRECEIVED\fR, \fIControl-B\fR behaves exactly like \fIControl-F\fR. .IP \fIControl-C\fR Aborts the protocol immediately. This should be a last resort to stopping a transmission as it will leave the remote \fIKERMIT\fR in an unknown state. .IP \fIControl-E\fR Aborts the protocol after sending an ERROR packet to the remote \fIKERMIT\fR. .IP \fIControl-D\fR Toggles \fIDEBUG\fR mode \fION\fR and \fIOFF.\fR This is helpful when trying to figure out why a particular host is unable to talk to \fIModel 4(p) KERMIT\fR. .IP \fI\fR If you type \fI\fR, \fIModel 4(p) KERMIT\fR will resend the current packet. .IP \fIControl-H\fR Displays the list of \fIKEYS\fR that you may press during a transfer. I.E. the keys described above. This is the same message that is printed when a SEND, GET, or RECEIVE command is issued. .sp 3 .NH Model 4(p) KERMIT Commands .sp .PP \fIModel 4(p) KERMIT\fR uses a subset of the the \fIDECSYSTEM-20\fR keyword style command language. Each keyword may be abbreviated to its minimum unique length. "?" may be typed to request a list of the available options for the current field at any point in a command. If insufficient characters have been typed to identify the current field uniquely, \fIModel 4(p) KERMIT\fR will display all available choices, and then reprompt to allow you to continue from that point. If there are sufficient characters, then only a single choice will be displayed. The following list of commands are available when using \fIModel 4(p) KERMIT\fR. .NH 2 BYE .sp .RS When talking to a remote \fIKERMIT\fR Server, this command should shut down a remote server and terminate the login that you had there. \fIModel 4(p) KERMIT\fR will then exit to \fITRSDOS Ready\fR. .RS .sp NOTE: Due to some deviations from the specification, some systems do not perform exactly in this manner. You should check the documentation of the \fIKERMIT\fR on the remote system in order to obtain the operation performed by this command. .RE .RE .NH 2 CLEAR .sp .RS .NH 3 INPUT-PORT .sp .RS \fIModel 4(p) KERMIT\fR uses the "Interrupt on received character available" feature of the COM/DVR communications line driver. This driver is part of the standard software on your system diskette. All characters received via the interrupt vector, are placed in a 256 byte circular buffer. This command clears all characters currently buffered. This is used most commonly with the INPUT, OUTPUT, PULSE, and PAUSE commands, none of which explicitly clear the input buffer. YOU MUST DO THIS YOURSELF. The execution of this command will \fInot\fR send an \fIXON\fR character to the communications port. This is also left up to you to do. .RE .NH 3 SCREEN .sp .RS As you would expect, this command clears the screen. .RE .RE .NH 2 CLOSE .sp .RS .NH 3 DEBUG-LOG .sp .RS Closes the file previously opened with the LOG DEBUG-LOG command. If there is not a debug logfile active, then a message is printed telling you so. .RE .NH 3 SESSION-LOG .sp .RS Closes the file previously opened with the LOG SESSION-LOG command. If no file is open, you will be advised so. .RE .NH 3 TRANSACTION-LOG .sp .RS Closes the file previously opened with the LOG TRANSACTION-LOG command. As with the other logfiles, if a file is not currently open, then a message to that affect is printed. .RE .NH 2 CONNECT (can be abbreviated to 'C') .sp .RS Establish a "virtual terminal" connection to any host that may be connected to the serial port, i.e. pass all typed characters to the serial port and display all input from the serial port on the screen. A two character sequence of characters is required to return the user to the \fIKERMIT\fR program. An escape character must be typed followed by a 'c' (Case is \fInot\fR significant). The default character is entered by pressing the key, and then and key, while holding the key down. Pressing '?' after the character will display a list of valid keystrokes that do helpful things during connect mode. The first time that you issue the \fICONNECT\fR command, a message will be displayed telling you what the character is. The character should generally be an uncommonly-used control character. The following characters are valid following the \fI\fR character, and generate specific actions. The actions are described beside the character. .RS .IP \fIC\fR Return to \fIModel 4(p) KERMIT\fR command level. The contents of the screen and the cursor location will be saved prior to displaying the \fIKERMIT\fR screen. When you reconnect to the \fIHOST\fR using the \fIKERMIT\fR command, \fICONNECT,\fR the old screen will be restored. .IP _? List available single-character commands, I.E. These commands. .IP \fIB\fR Send a TRUE modem break. .IP \fIR\fR Resume logging if file open, and Q was used previously to turn logging off. See the \fILOG\fR command for more information. .IP \fIQ\fR Quit logging to file but leave it open. .IP \fI0\ (zero)\fR Send a null (0) character out the communications port. .IP \fI\fR Send the \fI\fR character itself to the remote host. .RE .RE .NH 2 DIR partspec .sp .RS Produces a listing of the directory for "partspec". If partspec is not given, than the directory will be displayed for the \fIDEFAULT-DISK\fR drive as established by \fISET DEFAULT-DISK\fR. .RE .NH 2 EXIT .sp .RS Exit \fIModel 4(p) KERMIT\fR, and return to \fITRSDOS\fR. Before the \fIKERMIT\fR program is terminated, all open files will be closed. This includes the LOGFILES used for SESSION, TRANSACTION, and DEBUG logging. The *FO, and *FI devices will also be removed. .RE .NH 2 ECHO .sp .RS This command echoes text given as an argument to the screen. It can used in take files to put messages on the screen when TAKE-DISPLAY is OFF, although other uses are possible. .RE .NH 2 FINISH .sp .RS Shuts down a remote server without logging it out. Leaves you at \fIModel 4(p) KERMIT\fR command level. A subsequent \fICONNECT\fR command will reconnect you to the remote host. The \fIremote KERMIT\fR should return to the mode it was in prior to entering \fISERVER\fR mode. .RE .NH 2 GET filespec .sp .RS Get allows you to retrieve files from a remote host. Get works with either a \fISERVER\fR or a \fIKERMIT\fR that has initiated a \fISEND\fR command. Filespec is a filename compatible with \fIthat\fR system. When \fIModel 4(p) KERMIT\fR is talking to a \fIKERMIT\fR Server, you may include a filespec in a form legal to the \fIHOST KERMIT\fR. .RE .NH 2 INPUT .sp .RS INPUT provides one of 4 commands that provide an automatic logon facility. INPUT allows you to watch for the occurrence of certain text strings that are made up characters arriving in the communications port. This is useful in \fITAKE\fR files that can automatically log you onto a certain system. .PP When \fIINPUT\fR in initiated, it begins matching characters in the input to those given in the control string. When an exact match is found as established by the \fISET INPUT\fR options then \fIINPUT\fR will return to the \fIKERMIT\fR command level. If \fITAKE\fR is active than the next line of the \fITAKE\fR file will be read. The Control string may be comprised of any printable \fIASCII\fR characters. \fISPACE\fR must not occur as either the beginning or end of the string. .PP \fIASCII\fR character codes 0-32 are denoted as \fI\fR - \fI,\fR and \fI\fR represents character 127. The string \fI\fR signifies an immediate delay. The * should be replaced by a character. The significance of the character is this. Decimal 48 is subtracted from the \fIASCII\fR value of the character to obtain the number of seconds to delay. Thus, you can obtain delays 1-9 seconds, with no trickery. Delays longer than that will have to be calculated since the formula (ASCII code - 48 decimal) is used to calculate the binary value to use as a counter. The "*" should be replaced with the single proper ASCII character. .PP If you use \fI\fR in a \fIPULSE\fR command, it should be noted that it will only be done once. An alternative format for control characters is to explicitly type a carat ("^") preceding a character. The result of subtracting 64 from the \fIASCII\fR code for the character following will then be used. Since <, >, and ^ now have special meanings, you will need some way to specify them explicitly. To do this you should precede them with a backslash, "\\", character. In this case, backslash itself now must be represented as "\\\\". Finally, any and all characters can be represented using a string of the form \\nnn where nnn is 1 or more octal digits. nnn is evaluated, and the resulting value will be the ASCII value of the character. Some examples might be: .sp .RS INPUT login: .sp .RS Find the string "login:" followed by a space. .RE .sp INPUT ^M^Jenter \\\\userid\\\\: .sp .RS Find the string with a space followed by a carriage return followed by a line feed followed by the text "enter \\userid\\:" followed by carriage return and another linefeed. .RE .sp INPUT USERNAME\\77\\40 .sp .RS Find the string "USERNAME? ". Note that \\77 is the \fIONLY\fR way that a question mark can be specified since a question mark is recognized by the command stream as a request for help. .RE .RE .sp While input is waiting for a match, you may type characters on the keyboard to be transmitted. \fIBREAK\fR will abort the \fIINPUT\fR command and if \fITAKE\fR is active, close the take file. \fIESCAPE\fR will abort the INPUT command, but will just skip to the next line in a \fITAKE\fR file, if \fITAKE\fR is active. These same 2 actions apply to the \fIPULSE\fR command while no input has been received. .RE .NH 2 KILL wildspec .sp .RS This command performs the task of deleting one or more files from disk. \fIWildspec\fR is a wild card filespec that will be evaluated. All files that match the \fRwildspec\fR will be removed. A \fIwildspec\fR may contain any characters valid is a TRSDOS filespec, plus zero or more occurances of the characters '*', and '$'. These two characters have special meanings. .PP When comparing the \fIwildspec\fR with the name of a file, a '*' matches zero or more of the characters in the filename. E.g. If a file FOO/ASM is compared with '*/ASM', then it would match, because '*' can be thought of as 'FOO', and then '/ASM' is matched literally. M4*/ASM matches M4MIT/ASM, M4XFER/ASM, M4SEND/ASM, and any other filename that begins with M4, and ends with /ASM. The '$' character matches any single character. This means that FILE$/DOC matches the filename FILE1/DOC, but not FILE1A/DOC. .PP A drivespec may be appended to the \fIwildspec\fR to force the search for matches to be restricted to a single drive. An example might be M4*/ASM:1, which limits the matches to those file on drive 1. .PP Normally, only visible, nonsystem files are considered in the search. However, the inclusion of a parameter list containing either, or both of the keywords, INVIS or SYSTEM, will include invisible and/or system files. An example would be: .RS KILL (I,S) config/sys (I) backup/cmd .RE This example would cause \fIModel 4(p) KERMIT\fR to attempt to remove the two files listed. Note that as this example shows, you must specify the parameters with each \fIwildspec\fR that you wish to apply them to, as they are nullified each time that a new \fIwildspec\fR is evaluated. Other examples are given in the description of the \fISEND\fR command. .RE .NH 2 LOCAL (Can be abbreiviated to L) .sp .RS This command allows you to issue commands from within \fIModel 4(p) KERMIT\fR. You must remember where Model 4(p) KERMIT resides in memory, to assure that you do not overwrite it. KERMIT loads at 6000H, and continues up through LOW$. From within KERMIT, you can issue the command: .RS .sp LOCAL MEMORY .RE .sp to see where KERMIT ends. The value of LOW$ tells you this information. KERMIT was placed at 6000H to allow most of the TRSDOS library programs and commands to work in conjunction with KERMIT. Some commands extend above 3000H, and must have memory available up to approximately 5300H. The COPY command creates a problem because it apparently tries to examine HIGH$ to see if there is space to load a large portion of the source file into memory before writing it to the destination. This creates problems because KERMIT moves LOW$ up so that HIGH$ has a value that will allow additional high memory module to be loaded. It is suggested that you not use COPY while KERMIT is running, as the machine may crash when COPY completes. This is because it will have copied data into the KERMIT memory space. .RE .NH 2 LOG .RS .NH 3 DEBUG-LOG .sp .RS The debug log can be used to debug transfer problems that sometimes arrise when talking to a newly written KERMIT. The information written to the DEBUG-LOG is nearly identical to that which is displayed on the screen when the command, SET DEBUG ON, is issued, or the CTRL-D key is pressed during a transfer. This file can be closed explicitly with the \fICLOSE DEBUG-LOG\fR command. The EXIT command also causes an implicit closing of this file. .RE .NH 3 SESSION-LOG .sp .RS When CONNECTed to a foreign host as a terminal, this command establishes a log of the terminal session in the file specified. This function depends, to some extent, on the remote host's ability to do \fIXON/XOFF\fR flow control. Without \fIFLOW-CONTROL,\fR data may be lost when \fIKERMIT\fR writes to the file. The log file is closed by explicitly typing the \fIKERMIT\fR command \fICLOSE SESSION-LOG\fR or implicitly when \fIKERMIT\fR is exited via the \fIEXIT\fR command. It will also be closed if an I/O error occurs in file processing for the file involved. \fILOGGING\fR may be toggled on and off during \fICONNECT\fR using the sequence of keys described in the \fICONNECT\fR description. .RE .NH 3 TRANSACTION-LOG .sp .RS The transaction log is used to keep a record of the files transfered during a KERMIT session. The information includes whether or not the transaction was SENDING, or RECEIVING, the name of the file transfered, and the number of bytes involved in the transfer. .RE .RE .NH 2 LOGOUT .sp .RS Logout tells a \fIremote kermit server\fR to terminate itself, as well as your login session. When this is completed, you are left at \fIModel 4(p) KERMIT\fR command level. .RE .NH 2 OUTPUT .sp .RS This is the other side of the \fIINPUT\fR command. Control string follows the same conventions as in \fIINPUT,\fR and the resulting character(s) will be output to the communications port immediately. It should be noted that \fINO\fR characters other than what you specify are transmitted. In other words if you want to simulate typing some string, followed by pressing \fI,\fR then you will have to use a command similar to: .sp .RS OUTPUT mypassword .sp .RE .sp The \fI\fR will explicitly send the \fIASCII\fR character 13 to the communications port. .RE .NH 2 PAUSE .sp .RS This command is usually used in conjunction with \fIINPUT,\fR \fIOUTPUT,\fR and \fIPULSE\fR as a means of syncronizing \fIModel 4(p) KERMIT\fR to a remote host. A delay of the specified number of seconds will be generated based on the accuracy of the 60HZ interrupt. No means has been made for aborting the delay. The maximum delay is 65536 seconds by specifying 0 as the number. .RE .NH 2 PULSE .sp .RS This command is an extension/combination of \fIINPUT\fR and \fIOUTPUT.\fR It allows you to transmit one or more characters repeatedly until a character appears in the input port. The use of this command is valuable when logging onto systems that don't always respond immediately after the reception of some control character(s). For instance, you might (Now that all of the functions of this nature have been described) use the following commands as part of a logon sequence to log onto a computer system. .sp .RS SET INPUT CASE-IGNORE ON .br SET INPUT DISPLAY ON .br SET OUTPUT HOST-ECHO ON .br SET OUTPUT DISPLAY ON .br CLEAR INPUT-PORT .br PULSE ^T .br INPUT XYZ: .br PAUSE 2 .br CLEAR INPUT-PORT .br PULSE .br INPUT Username: .br OUTPUT joeblow .br INPUT Terminal type: .br OUTPUT h19 .br SET KEY 8 .br SET KEY 128 .RE .sp After you study this awhile, it should make sense. If these commands are placed into a \fITAKE\fR file, then you could use a \fICONNECT\fR command after the last command, to connect immediately to the host. If this is done, then \fIonly\fR after you escape back to \fIModel 4(p) KERMIT\fR, will the \fITAKE\fR file finally be closed. .RE .NH 2 RECEIVE .RS This command is synonomous with the GET command. It may be abbreviated to the single character 'R', as in: .RS .sp R *.asm .sp .RE .RE .NH 2 REMOTE .sp .RS \fIRemote\fR commands are not supported in totality by all \fIservers\fR. If a \fIserver\fR supports remote commands, then \fIremote help\fR should display all of the commands available to the \fIremote\fR user of the server. Below are descriptions of the \fIremote\fR commands that \fIModel 4(p) KERMIT\fR knows how to send to a \fIremote server\fR. The arguments to most commands are dependent on the \fIremote\fR system. You should be familiar with any system before using the \fIremote server\fR commands available from that server. Usually only a small number of these commands are supported since some require abilities that some operating systems just don't have. .sp .NH 3 CLOSE-LOG .sp .RS Close a remote \fILOG\fR previously opened via the command \fIREMOTE START-LOG\fR. .RE .NH 3 COPY .sp .RS Copy one file to another. .RE .NH 3 CWD .sp .RS If a particular server's operating system supports the concept of separate directories, then this command will allow you to change to a different directory. .RE .NH 3 DELETE .sp .RS Deletes file(s) from the \fIremote\fR system. Any arguments will probably be file names in the format of the \fIremote\fR system. .RE .NH 3 DIR .sp .RS Display a list of files on the \fIremote\fR system. .RE .NH 3 DISK .sp .RS Display information about disk utilization on the \fIremote\fR system. .RE .NH 3 HELP .sp .RS Get information about \fIremote\fR capabilities on the \fIremote\fR system. .RE .NH 3 HOST .sp .RS Execute a command on the \fIremote\fR system. .RE .NH 3 KERMIT .sp .RS Execute a \fIKERMIT\fR command on the \fIremote\fR system. This command should accept a normal \fIKERMIT\fR command as an argument. The command, if valid, will then be executed by the remote \fIKERMIT\fR server. .RE .NH 3 LOGIN .sp .RS Create a login entity on the \fIremote\fR system. This may be incorporated into a dedicated server. .RE .NH 3 MESSAGE .sp .RS Send a message to a user on the \fIremote\fR system. .RE .NH 3 PROGRAM .sp .RS Feed command input to a command executing on the remote system, or control the execution of a program. .RE .NH 3 QUERY-VARIABLE .sp .RS Get the value of a variable maintained on the \fIremote\fR system. .RE .NH 3 RENAME .sp .RS Change the name of a file on the \fIremote\fR system. .RE .NH 3 SEND-LOG .sp .RS Tells the server to close any open log, and then transfer it to the user. .RE .NH 3 SERVER-STATUS .sp .RS Retrieve certain information about the status of a REMOTE server. The information returned is dependent on the REMOTE system. .RE .NH 3 SET-VARIABLE .sp .RS Set the value of a variable on the \fIremote\fR system. .RE .NH 3 START-LOG .sp .RS Start a transaction log on the \fIremote\fR system. .RE .NH 3 STOP-LOG .sp .RS Stops logging to the log file started by the \fIREMOTE START-LOG\fR command. The file is not closed. Logging may be started again by using the the command, \fIREMOTE START-LOG\fR. .RE .NH 3 TYPE .sp .RS Display the contents of the file/files given as arguments. The \fIremote\fR server should use the \fIKERMIT\fR protocol to send the contents of the specified file/files to \fIModel 4(p) KERMIT\fR. The file contents will be displayed on the screen using the *SO device. .RE .NH 3 WHO .sp .RS Display a list of users on the \fIremote\fR system. .RE .RE .NH 2 SEND (May be abbreviated to 'S'); .sp .RS File specifications may contain wild card characters. The recognized wild card characters are '*' and '$'. '*' means zero or more of any character. '$' means exactly one of any character. There are a lot of specifics associated with wild carding, and search order through the drives. .PP When files by the same name exist on different drives, a wild card match of one will also match all other occurances. e.g. if drive 0 contains the file report/dat, and report.dat also exist on drive 1, then the command 'SEND */dat' will collect both names for sending. On the other hand, other variations can be used to send only one of the 2 files. 'SEND */dat:1' will only match files on drive 1. Another alternative would be 'SEND report/dat:1' which would send only report/dat on drive 1. .PP Case is NOT significant, so both REPORT/DAT and report/dat are identical. '/' is not significantly different from other characters in a file name, so "*/*" is the same as "*" for all file names with an extension. "*/*", however, does not match names of the form "data", "fred", "file", "temp", or others without extensions. Other examples are given in the description of the \fIKILL\fR command. .RE .NH 2 SET .sp .RS Set the specified parameter to the specified value. Possible settings: .sp .NH 3 BELL ON (or OFF) .sp .RS When \fIDUMB\fR terminal emulation is in effect, a simple noise generator is used to produce a tone like a bell each time the \fIBELL\fR character is received. If you don't like it, than use \fISET BELL OFF\fR to disable it. .RE .NH 3 BLOCK-CHECK-TYPE .sp .RS The options are: .NH 4 1 (character checksum) .sp .RS Normal, default, standard 6-bit checksum. .RE .NH 4 2 (character checksum) .sp .RS A 12-bit checksum encoded as two characters. .RE .NH 4 3 (character crc-ccitt) .sp .RS A 16-bit CCITT-format Cyclic Redundancy Check, encoded as 3 characters. .RE .sp The 2 and 3 character options should only be used under conditions of extreme line noise. Many implementations of \fIKERMIT\fR only support the single character checksum. .RE .NH 3 DEBUGGING OFF (or ON) .sp .RS When transmitting or receiving packets, controls whether the packets are displayed on the local screen. .RE .NH 3 DEFAULT-DISK .sp .RS The default-drive value is used for received files. The file names created by \fIModel 4(p) KERMIT\fR will have a ':' and the default drive number affixed to the end so that they will be forced to be saved on the selected drive. .RE .NH 3 EIGHT-BIT-QUOTING ON (or OFF) .sp .RS This command enables or disables 8th bit quoting. This is useful when a full 8 bit path is available for binary file transfers. .RE .NH 3 EMULATION NONE (or DUMB) .sp .RS When connected as a terminal to a foreign host, \fISET EMULATION\fR controls whether the Model 4 emulates no terminal, allowing the use of a terminal filter, or whether a \fIDUMB\fR terminal emulation is used. No emulation is the default. .RE .NH 3 ESCAPE .sp .RS Change the escape character for virtual terminal connections. \fIModel 4(p) KERMIT\fR will prompt you for the new escape character, which you type in locally. .RE .NH 3 FILE .RS .NH 4 DISPOSITION KEEP (or DISCARD) .sp .RS When the transfer of a file is interrupted, this tells Model 4(p) KERMIT what to do if it receives only a partial file. If FILE-DISPOSITION is DISCARD, then any partial file is removed. Otherwise, the file is left as it is when a transfer is interrupted. .RE .NH 4 TYPE (ASCII or BINARY) .sp .RS Tells \fIModel 4(p) KERMIT\fR how to deal with the file being sent/received. It is \fIIMPORTANT\fR to tell KERMIT if the file is in \fIASCII\fR when sending to a \fINON Model 4(p) KERMIT\fR. The action taken with this value is as follows. If \fIASCII\fR mode is set, then CR-LF pairs of characters are translated to CR on input, and CR is translated to CR-LF on output. When binary mode is in effect, this translation does not occur. .RE .RE .NH 3 FLOW-CONTROL XON/XOFF (or NONE) .sp .RS When this feature is set to \fIXON/XOFF\fR (the default), \fIModel 4(p) KERMIT\fR will try its best to obey and use \fIXON\fR characters and \fIXOFF\fR characters for all transmitions through the communications port. \fINONE\fR will disable all attempts at this sort of flow- control. .RE .NH 3 INPUT .RS .NH 4 CASE-IGNORE OFF (or ON) .sp .RS Controls whether of not case matching is done on characters during the input command. In most instances, you will want this \fION\fR. .RE .NH 4 DISPLAY OFF (or ON) .sp .RS Controls the display of characters that are input during the execution of the \fIINPUT\fR command. .RE .RE .NH 3 KEY .sp .RS This command allows you to send an arbitrary (the length of the \fIKERMIT\fR command line is the limit) string with a single key stroke. The definition of string is identical for that of the \fIINPUT\fR, \fIOUTPUT\fR, and \fIPAUSE\fR commands. KEY VALUE is the ASCII value of the key stroke as given in the TRSDOS manual. If KEY VALUE is not given, then you will be asked to press the key corresponding to the key that you wish to define. All keys are valid in \fIstring\fR except BREAK. Pressing BREAK signals the end of the definition string. While in \fICONNECT\fR mode, typing the defined key will cause the characters typed as the definition to be typed instead. Defining a key to have a \fINULL\fR length deletes any previous definition. .RE .NH 3 LOCAL-ECHO OFF (or ON) .sp .RS When you \fICONNECT\fR to a remote host, you must set \fILOCAL-ECHO ON\fR if the host is half duplex, \fIOFF\fR if full duplex. .RE .NH 3 OUTPUT .RS .NH 4 HOST-ECHO ON (or OFF) .sp .RS When using \fIOUTPUT\fR, and communicating with a remote host, the host commonly echoes the characters as you type. Since \fIOUTPUT\fR effectively types characters for you, these characters may be echoed back. If \fIHOST-ECHO\fR is \fION\fR, \fIOUTPUT\fR will wait for the echoed character to reappear in the input buffer before it sends the next. In the example for sending and receiving raw data, that is above, setting \fIHOST-ECHO ON\fR, will enable us to remove the \fIINPUT TYPE MYPROG.DAT\fR command. Control characters are \fINOT\fR normally echoed, so this feature when set \fION\fR, will not wait for them. If you must catch the echo of a control character, then follow the \fIOUTPUT\fR command with the appropriate \fIINPUT\fR command. .RE .NH 4 DISPLAY OFF (or ON) .sp .RS This parameter when on controls the display of characters that are received when \fIHOST-ECHO\fR is \fION\fR. Otherwise, They are displayed based on the status of the \fILOCAL-ECHO\fR setting. .RE .RE .NH 3 PRINTER OFF (or ON) .sp .RS Turns copying of \fICONNECT\fR session to printer on and off. With \fIFLOW-CONTROL\fR turned on, and a sending host that will acknowledge the \fIXOFF\fR, you should have no problems using the printer continuously. .RE .NH 3 RECEIVE .RS .NH 4 END-OF-LINE .sp .RS Set the end of line character in packets to some other character than \fI\fR which is the default. .RE .NH 4 PAD-CHAR .sp .RS If the host you are communicating with needs one or more padding characters before it receives actual data during packet transfers, this character will be sent \fIPADDING\fR times. .RE .NH 4 PADDING .sp .RS The repeat count for the number of times the padding character is transmitted. .RE .NH 4 QUOTE-CHARACTER .sp .RS The character used to quote control characters. The default is pound "#" .RE .NH 4 START-OF-PACKET .sp .RS The character used to syncronize the packets that \fIKERMIT\fR transmits. By default \fI\fR. .RE .NH 4 TIME-OUT .sp .RS \fIModel 4(p) KERMIT\fR uses this value as the number of seconds to wait for a response to a packet. If no response is received within the number of seconds given, then the packet for which the response has not been received is retransmitted. .RE .NH 4 TURN-CHAR .sp .RS The character used to syncronize KERMIT when used over a half duplex line. \fIModel 4(p) KERMIT\fR will wait for this character at the end of a packet, and will send the SEND TURN-CHAR at the end of a packet. .RE .RE .NH 3 SEND .RS .NH 4 END-OF-LINE .sp .RS Set the end of line character in packets to some other character than \fI\fR which is the default. .RE .NH 4 PAD-CHAR .sp .RS If the host you are communicating with needs one or more padding characters before it receives actual data during packet transfers, this character will be sent \fIPADDING\fR times. .RE .NH 4 PADDING .sp .RS The repeat count for the number of times the padding character is transmitted. .RE .NH 4 QUOTE-CHARACTER .sp .RS The character used to quote control characters. The default is pound "#" .RE .NH 4 START-OF-PACKET .sp .RS The character used to syncronize the packets that \fIKERMIT\fR transmits. By default \fI\fR. .RE .NH 4 TIME-OUT .sp .RS This value is given to the \fIother\fR host as its' timeout value. You should assure that this is different from the RECEIVE TIME-OUT value so that both timeouts do not occur simultaneously. .RE .NH 4 TURN-CHAR .sp .RS The character used to syncronize KERMIT when used over a half duplex line. \fIModel 4(p) KERMIT\fR will send this character at the end of a packet. The RECEIVE TURN-CHAR will be waited for before data is transmitted. .RE .RE .NH 3 TAKE-DISPLAY OFF (or ON) .sp .RS Controls the display of \fITAKE\fR files as they are executed. By default this feature is off. .RE .NH 3 WARNING ON (or OFF) .sp .RS Warns user if filename conflicts when receiving files from remote host, and attempt to generate a unique name by modifying the given one. \fION\fR by default. .RE .RE .NH 2 SETCOM .sp .RS Sets/shows the status of the communications driver, \fICOM/DVR\fR. If no arguments are given, than the current status will be shown. Any arguments must be enclosed in parenthesis as the result of this command, is a generated \fITRSDOS\fR command as in: .RS .sp SETCOM (B=9600,P=N,W=8) .RE .sp The default values are established according to you. If you set up the driver for a certain configuration, and then use \fISYSGEN\fR to save it, then that will be the default. \fINO\fR sysgen should give you: .RS .sp 300 BAUD .br EVEN PARITY .br DTR=YES .br 7 DATA BITS .br 1 STOP BIT .RE .RE .sp .NH 2 SHOW .sp .RS Allows one or ALL of the options of the \fISET\fR command to be displayed. Using the "?" feature will aid you if you can't figure out where to find something. All of the things that can be SET can be displayed. The items not listed below can be displayed by using a command like: .RS .sp SHOW BLOCK .RE .sp or .sp .RS SHOW DEFAULT .RE .sp SHOW ALL will display all of the set values except keys. You must use SHOW KEY to see these values. .RE .NH 3 SEND .sp .RS Displays all options described under the \fISET SEND\fR command. .RE .NH 3 RECEIVE .sp .RS Displays all options described under the \fISET RECEIVE\fR command. .RE .NH 3 KEY .sp .RS If is specified, then the definition for the specified key number is display. Otherwise, a prompt is issued for the user to type the keystroke that should be taken as the key to display. \\nnn is used to display all values greater than 127. ^x where x is a character 64 greater than 0 through 31, and 127 is used to display control characters. Any other printable ASCII character is displayed normally. .RE .RE .NH 2 STATUS .sp .RS Shows certain information about the status of \fIModel 4(p) KERMIT\fR. Items currently displayed include the amount of space left in the \fIKEY\fR definition table, the number of bytes written to files during transfers, the number of bytes read from files during transfers, as well as statistics on the latest transfer. .RE .NH 2 TAKE .sp .RS TAKE allows commands to be stored in a file, and then executed by the \fIKERMIT\fR command interpreter. Only \fIone\fR level of \fITAKE\fR files is supported. This means that a \fITAKE\fR command can not appear inside of a \fITAKE\fR file. No checking is done to enforce this, so good luck if you want to try it. When \fIKERMIT\fR is first entered, a check is made for a file called \fIKERMIT/INI\fR on all of the active disk drives as per normal \fITRSDOS\fR searching order. If it is found, than it is used as a \fITAKE\fR file where you can store initialization commands. Pressing the \fIBREAK\fR key, or the \fIENTER\fR key during the startup of KERMIT (before the TAKE file is opened) will cause \fIKERMIT\fR to skip processing of the \fITAKE\fR file. .RE .sp 3 .NH Setting up to use Model 4(p) KERMIT .PP To use \fIModel 4(p) KERMIT\fR, you need to have your Model 4 set up properly. The program expects that the *CL device will be driven by the COM/DVR Communications Driver that comes with TRSDOS. It also expects that the *SO device is ROUTED to the *DO device, and that the *SI device is ROUTED to the *KI device. The former 2 are the defaults, and in general, you should not worry about them, unless you have changed them. Setting up the *CL device involves typing the command: .RS .sp SET *CL COM/DVR .RE .sp at the \fITRSDOS Ready\fR prompt. If you do not do this, you will get a message of the form .RS .sp Can't find *CL DCB .RE .sp from \fIModel 4(p) KERMIT\fR when it is starting up. The program will return control to TRSDOS after issuing this message, as it is a fatal error. .PP \fRModel 4(p) KERMIT\fR is not a small program. It occupies memory starting at 6000H, and extends up past 0D300H. If you have parts of TRSDOS resident (Using the SYSTEM (SYSRES=....) command), or perhaps other filters or memory resident modules, then you should make sure that they do not extend below the maximum address used by the program. The last memory address used by \fIModel 4(p) KERMIT\fR can be obtained by using the command .RS .sp LOCAL MEMORY .RE .sp from within the \fIModel 4(p) KERMIT\fR program. .sp 3 .NH Installation .PP To install \fIModel 4(p) KERMIT\fR, you must obtain the two files \fIM4BOO.BAS\fR and \fIM4MIT.HEX\fR. Because of the size of the executable, the hex file could not be placed into a basic program as data statements. Instead, the basic program opens and reads the file \fIM4MIT.HEX\fR. This file is an \fIASCII\fR image of the executable. All that needs to be done, is to run the \fIBASIC\fR program which will convert the file back to its original binary format. The resulting executable should probably be called \fIKERMIT/CMD\fR. Follow the prompts of the BASIC program and there should not be any problems. .NH Building \fIModel 4(p) KERMIT\fR from the Source. .PP The Source for \fIModel 4(p) KERMIT\fR is in approximately 15 modules. The names of the modules are: .RS .IP M4ADD/ASM 15 Code for miscellaneous routines. .IP M4CMD/ASM Command parser code. .IP M4EQU/ASM Mosts constants are defined here .IP M4FILE/ASM Additional logfile code such as the LOG command, and the CLOSE command. .IP M4GET/ASM Receive file routines + other miscellany. .IP M4KEY/ASM Code for handling the SET KEY functions .IP M4LOG/ASM INPUT, OUTPUT, PAUSE, PULSE commands. .IP M4MAC/ASM Macros used in the program .IP M4MIT/ASM Main entry and some command routines. .IP M4PKT/ASM New packet routines for encoding and decoding packets. .IP M4RMT/ASM The base of what will be the remote command. .IP M4SEND/ASM Send file routines. .IP M4SET/ASM Set options routines. .IP M4SHOW/ASM Show settings routines. .IP M4STR/ASM The majority of storage, prompts, and messages. .IP M4TERM/ASM Terminal Emulation, and I/O routines. .IP M4WILD/ASM Wild card file name processing. .IP M4XFER/ASM File processing, and some packet stuff. .RE .PP \fIModel 4(p) KERMIT\fR was developed using the \fIEDAS\fR assembler from Misosys. Other macro assemblers should be able to assemble the program with minor conversions. \fIM4MIT/ASM\fR is the main source module. It will call the other source files into the assembly (using the *GET directive) as needed. If any system calls need to be changed, they are all defined in \fIM4ADD/ASM\fR for the most part. All of the SVC's are coded in \fIM4ADD/ASM\fR as subroutines that are accessed by CALL Xaaaaa, where aaaaa is the name of the \fITRSDOS\fR supervisor call (SVC) without the "@" sign. .PP If this version is moved to another OS, there are several things that you should consider. The things that come to mind are: .sp .RS .IP 1. 5 Consider the format of the TRSDOS directory structure. The wild card routines depend on this structure for validating directory entries, and for retrieving the file name. .IP 2. There are 2 places where real time counting is required. The delay specified in a PAUSE statement can be handled with a counter, as all other processing is halted (except the interrupt tasks) during the pause. Currently, the Real Time Clock task is used to measure the appropriate delay. The other use of a Real Time counter occurs in the Receive packet timeout. This must be handled using asyncronous processes in order to be accurate. .IP 3. There exist code at the beginnning and end of the segment that accesses the screen which outputs the bytes 14, and 15 to the *DO device. These are used to force the cursor to be invisible before the screen is accessed, and to then make it reappear after the screen access is completed. .IP 4. The interrupt driven receiver must also be delt with. The code in the routine SETINT, establishes the interrupt vector that the *CL driver will call when a "character received interrupt" is generated. .IP 5. In many instances, the characters having values 16, and 17 are used to enable, and disable reverse video respectively. If the driver for *DO does not recognize this convention, as the current one does, then these characters must be handled in some manner. I.E. either removed from the source, or filtered from the terminal output stream. The PRTSTR() routine is a good place to mask these characters at, as it is the sole source of output for strings containing these type of characters. .RE .sp .PP It should be noted that \fIKERMIT/CMD\fR loads into RAM at 6000H. This avoids high memory filters and drivers, and also allows use of \fITRSDOS\fR library commands that use low memory beyond 3000H, as FORMAT, and BACKUP do. Exclusive use is made of the *DO device for screen output from the KERMIT program, for informational messages and the like. During connect mode, *SI and *SO are used as the input and output devices to allow filters to be attached that will not effect the operation of \fIModel 4(p) KERMIT\fR during command operations. If you install a different driver or filter it must be compatible in these areas. .NH Performance Specifics of Model 4(p) KERMIT .PP The \fIModel 4(p) KERMIT\fR has been tested and proven to work properly at 9600 BAUD with flow control on, transferring files between 2 Model 4's. What makes the \fIModel 4(p) KERMIT\fR perform so well is the idea of flow control, and the interrupt driven receiver. With out these features, I expect that 2400 baud would be the reliable limit. Flow control can be disabled at speeds less than or equal to ~2400 baud, but greater speeds require that flow control be functional in order to protect the integrity of data in the input buffer. .sp 3 .NH The Heath 19 Filter .PP The files \fIM4H191.ASM, M4H192.ASM, M4H19.MAC\fR, and \fIM4H19.EQU\fR make up the sources for a Heath 19 terminal emulation filter for the TRS-80 Models 4 and 4p. The assembler used was EDAS by Misosys. To build the filter from sources, you need the above 4 files on a disk. \fIM4H191.ASM\fR is the main source module, and it *GETs all the other necessary files. .PP The structure of the program is pretty simple. Single character (non escape) sequences, are passed to the filtered device via the \fI@CHNIO\fR svc. This filter depends on the \fITRSDOS *DO\fR driver being at the end of the chain. Several control characters are merely translated, and then the new values are passed to *DO. .PP A multi-character escape sequence is handled by remembering the previous characters that the filter was passed. The previous characters are remembered by the presence of a non-zero value in the contents of \fISTATE\fR. The value in \fISTATE\fR represents the address of the code to handle the next character, given the previous string of characters. .PP The filter is relocatable, but \fIMUST\fR reside below screen memory because it accesses it directly when performing several of the advanced terminal functions. For this reason, it will never load \fIabove F3ffH\fR. .NH The SETH19 Program .PP The \fISETH19\fR program allows you to configure a few options that are available to you when using the \fIH19 filter\fR. The \fISETH19\fR program is created from the sources \fIM4H19S.ASM, M4H19.EQU,\fR and \fIM4H19.MAC\fR. \fIM4H19S.ASM\fR is the main source module, and will *GET the other 2 files. The program supports a few parameters that are listed below. .RS .sp .IP REMOVE 15 Remove and reclaim if possible. .IP DURATION Length of BELL tone. .IP FREQUENCY Frequency value (bigger value is lower tone) for BELL. .IP BELL Turn audible BELL ON or OFF. .IP BLOCK Block cursor character. .IP CURSOR Normal cursor character. .IP STRIP8 Control display of 8 bit data. .IP HELP Displays information similiar to this. .IP SHOW Displays the current settings of the parameters, this is the default. .LP .RE These options are specified when you invoke \fISETH19\fR, as per the usual TRSDOS 6.x parameter list. An example is shown below: .RS .sp SETH19 (BLOCK=191,CURSOR=23,BELL=ON,SHOW) .RE .PP This command sets the normal CURSOR, and the edit mode CURSOR values, as well as turning the audible bell on. The show parameter causes 2 lines similiar to those below to be printed on the screen. .RS .sp Normal Cursor: 23, Block Cursor: 191 .br Bell: ON, Frequency: 20, Duration: 120 .br Strip8: ON .sp .RE .PP The REMOVE option takes several things for granted, as it tries to thoroughly remove the device. It assumes that the H19 filter is attached to the *HP device, and that this device is a filter hooked to *SO. Further more, it assumes that *SO is routed to *DO. .PP This particular set up can be used easily if the following commands are used to set up the filter: .RS .sp SET *HP H19/FLT FILTER *SO *HP .RE .sp This is assuming that *SO is routed to *DO. The SETH19 command will perform these very operations if you invoke it, and the memory module, \fI$HEATH\fR, is not in place. .PP The other parameters to the SETH19 command can be used to control certain preferable options to the filter. Setting \fIBELL\fR off causes the filter to flash the screen when it receives an ASCII(7) character. If BELL is set \fION\fR, then an audible bell is issued when an ASCII(7) is received. .PP When BELL is ON, then the \fIDURATION,\fR and \fIFREQUENCY\fR parameters take effect. These 2 parameters select the length and pitch, respectively, of the BELL tone. The FREQUENCY value is used as a delay between oscillations of the sound port, so the bigger the number, the lower the tone will be. .PP The \fIdefault DURATION\fR is set to 20, and the FREQUENCY is set to 125. You can adjust them as you please. The DURATION is inversely proportional to the FREQUENCY, since the delay caused by the FREQUENCY value is part of the overall DURATION of the sound. This means that as you increase FREQUENCY, you must \fIdecrease\fR DURATION to maintain the same length of BELL, and vice-versa. .PP The \fIBLOCK\fR and \fICURSOR\fR parameters are used to control the characters that are used as the cursor by the H19 filter. The H19 terminal has the ability to use a visual mode cursor, or a line mode cursor. Since the normal visual mode cursor is usually a block cursor, the parameter BLOCK is used to set the ASCII value of the visual mode cursor. The CURSOR parameter sets the normal line mode cursor. .PP The switch between cursors must be done by the HOST computer that is attached to the Model 4's communications port. There is no magic to when the BLOCK cursor is selected, see the description of the recognized control sequences below. .PP The STRIP8 parameter controls whether or not data is printed on the screen with the eighth bit set. Normally, the filter now trims the eighth bit off so that parity can be ignored. The command .RS .sp SETH19 (STRIP8=NO) .RE .sp will cause the eighth bit to not be stripped. That is to say, data will be used as it is received by the filter. Note that when this is done, some control characters with parity bits attached may not be recognized. .PP .NH Future modifications .PP It should be fairly straight forward to build extra states into the filter so that it will recognize the ANSI 3.64 sequences for the operations the filter knows how to perform. Full support of all the ANSI 3.64 sequences would be a non-trivial investment in time. The best bet here would, be a completely new device driver, since the overhead of going to *DO is already costly, and trying to implement scroll regions with *DO would be a HACK at best. If somebody wants to do the conversion, I would like to have a copy of the result. .NH HEATH-19 filter capabilities .PP The HEATH-19 terminal supports several advanced video capabilities that make it an ideal source for a terminal emulation package. Below is a list of the functions supported by the Model 4(p) H-19 emulator, and the escape sequences that perform the operations. .NH Heath/Zenith-19 Control Codes .PP The Heath/Zenith-19 terminal is equivalent to the DEC VT52 with extensions for line and character insertion and deletion. Items marked with an asterisk are not currently supported by Model 4(p) H19 emulation. .sp 2 .na .nf Cursor Functions .sp Sequence Mnemonic Definition .br ESC H HCUH Cursor Home .br ESC C HCUF Cursor Forward .br ESC D HCUB Cursor Backward .br ESC B HCUD Cursor Down .br ESC A HCUU Cursor Up .br ESC I HRI Reverse Index .br *ESC n HCPR Cursor Position Report .br ESC j HSCP Save Cursor Position .br ESC k HRCP Set Cursor to Previously Saved Position .br ESC Y HDCA Direct Cursor Addressing, 1-based: .br 31+line# 31+col# (same as VT52) .sp 3 Erasing and Editing .sp Sequence Mnemonic Definition .br ESC E HCD Clear Display (Shift Erase) .br ESC b HBD Erase Beginning of Display .br ESC J HEOP Erase to End of Page (Erase Key) .br ESC l HEL Erase Entire Line .br ESC o HEBL Erase Beginning of Line .br ESC K HEOL Erase to End of Line .br ESC L HIL Insert Line .br ESC M HDL Delete Line .br ESC N HDCH Delete Character .br ESC @ HEIM Enter Insert Character Mode .br ESC O HERM Exit Insert Character Mode .sp 3 Configuration .sp Sequence Mnemonic Definition .br *ESC z HRAM Reset to Power-Up Configuration .br *ESC r Bn HMBR Modify Baud Rate: Bn= .br A=110, B=150, C=300, D=600, E=1200, .br F=1800, G=2000, H=2400, I=3600, J=4800, .br K=7200, L=9600, M=19200 .sp 2 ESC x Ps HSM Set Mode(s): Ps= .br * 1 = Enable 25th line .br * 2 = No key click .br * 3 = Hold screen mode .br 4 = Block cursor .br 5 = Cursor off .br * 6 = Keypad shifted .br * 7 = Alternate keypad mode .br 8 = Auto line feed on CR .br 9 = Auto CR on line feed .sp 2 ESC y Ps HRM Reset mode(s): Ps= .br * 1 = Disable 25th line .br * 2 = Enable key click .br * 3 = Exit hold screen mode .br 4 = Underscore cursor .br 5 = Cursor on .br * 6 = Keypad unshifted .br * 7 = Exit alternate keypad mode .br 8 = No auto line feed .br 9 = No auto CR .sp 2 *ESC < HEAM Enter ANSI Mode .sp Modes of Operation .sp Sequence Mnemonic Definition .br *ESC [ HEHS Enter Hold Screen Mode .br *ESC \\ HXHS Exit Hold Screen Mode .br ESC p HERV Enter Reverse Video Mode .br ESC q HXRV Exit Reverse Video Mode .br *ESC F HEGM Enter Graphics Mode .br *ESC G HXGM Exit Graphics Mode .br *ESC t HEKS Enter Keypad Shifted Mode .br *ESC u HXKS Exit Keypad Shifted Mode .br *ESC = HAKM Enter Alternate Keypad Mode .br *ESC > HXAM Exit Alternate Keypad Mode .sp 3 Additional Operations .sp Sequence Mnemonic Definition .br *ESC } HDK Keyboard Disable .br *ESC { HEK Keyboard Enable .br *ESC v HEWA Wrap Around at End of Line .br *ESC w HXWA Discard at End of Line .br *ESC Z HID Identify as VT52 (ESC / K) .br *ESC ] HX25 Transmit 25th Line .br *ESC # HXMP Transmit Page .sp 3 Enhanced Character Support .sp ESC [ p1 ; ... pn m Set Graphics Rendition .br where p1, ..., pn are chosen from the following: .br *0 Reset to normal character display. .br *1 Display characters in high intensity. .br *4 Display characters underlined. .br *5 Display characters blinking. .br *7 Display characters in reverse video. .br .fo .ad .sp 2 .PP The Heath-19 transmits the following sequences, but it will not respond to them if they are received. Model 4(p) Kermit will transmit them only if they are programmed with SET KEY. .sp .nf .na ESC S HF1 Function Key #1 .br ESC T HF2 Function Key #2 .br ESC U HF3 Function Key #3 .br ESC V HF4 Function Key #4 .br ESC W HF5 Function Key #5 .br ESC P HF7 Function Key #7 .br ESC Q HF8 Function Key #8 .br ESC R HF9 Function Key #9 .fo .PP My thanks to Michael Carter and Roland Stolfa for their help in testing and debugging this implementation. .sp 2 .nf Gregg Wonderly .br Department of Computing and Information Sciences .br Oklahoma State University .sp 2 UUCP: {cbosgd, ea, ihnp4, isucs1, mcvax, uokvax}!okstate!gregg .br ARPA: gregg@A.CS.OKSTATE.EDU