IMD 1.18: 22/01/1996 7:17:26 micro cornucopia kaypro user guide disk 23 fast terminal software and new bye     -23-DISKDOC10GINSTLSUB10INSTALSUB10ZCPR HEX$ 2INSTALLSUB2ZCPR HEX$484ZCPR HEX$4INSTALLSUBBYE ASM !"#$%&'()BYE ASM*+,-./0123456789BYE ASM:;<=>?@ABCDEFGHIBYE ASMvJKLMNOPQRSTUVWXBYE COMYZ[BYEZCPR DOCC\]^_`abcdCRC COMefgCRC DOCh Kaypro Disk #23 Remote CP/M Utilities Micro Cornucopia PO Box 233 Bend, OR 97709 This disk contains the necessary programs to make your Kaypro into a Remote CP/M (RCP/M) system with a Hayes (or Hayes compatible) SmartModem. BYE.COM BYE.ASM BYE is the main program in a remote system. It does the following: 1. Causes your Smartmodem to Hang up the phone and wait for a call. 2. Answers incoming calls and Sets the baud rate to 300 or 1200 to CRCKLISTCRCiEX14 COMjklEX14 DOC/mnopqrGINSTALLSUBsINTTERM COMtuvwINTTERM MACxyz{|}~INTTERM MAC README TXTXLATETBLASMXMODEM ASMXMODEM ASMXMODEM ASMQXMODEM COMXMODEM DOC match the callers rate. 3. Allows the caller access to CP/M. 4. Hangs up the phone if the carrier is lost or the caller types BYE. 5. Resets the system and waits for the next call. There are many options available with BYE to make your system respond any way you want. Some of these are: 1. Require a password before access to CP/M is granted. 2. Limit the Disk Drives and User Areas the remote user has access to. 3. Keep track of how many calls come in. 4. Print the remote user's out  put on your printer. BYE.ASM is the assembly language source for BYE.COM and can be editted with your word processor to choose the options you desire and then assembled with ASM.COM by entering: ASM BYE And then: LOAD BYE to produce a new BYE.COM file. The option sections are commented for easy selection. XMODEM.COM XMODEM.ASM XMODEM is a program that allows you to cause the remote system to send you a file using the Ward Christenson (MODEM7) Protocol with out having anyone at ttructions are at the beginning of the XLATETBL.ASM file. To use, just connect your Kaypro to another computer from your Serial Data Port to the other computers terminal port and enter: INTTERM +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ To verify the files on this disk enter: CRC +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ :10D40000C3E1D4C3DDD450002020202020202020E0 :08D41000202020202020200034 :04D4590008D417D408 :10D47700434F4D00242424202020202053554200D0 :01D4870000A4 :10D4BC001600004449522069D84C4953541AD95487 :10D4CC005950451ED955534552B7D944465520C1DC :10D4DC00D9AF3207D43177D4C5791F1F1F1FE60F80 :10D4EC005FCD25D6CDE8D53209D5C179E60F3239D5 :10D4FC00D62806CDEDD53209D5117AD43E00B72FFA :10D50C00C407D62F3209D53A07D4B720263177D4A1 :10D51C00CD87D5CDDDD5C641CD8ED5CD23D6FE0A52 :10D52C003809D60AF53E31CD8ED5F1C630CD8ED52he remote system keyboard. It is kept on the remote system (the one running BYE) and is used by the remote user to send and receive files. XMODEM.DOC describes how to use this program and XMODEM.ASM is the assembly language source which may be assembled with ASM.COM. ZCPR and Related Files These contain a protected version of ZCPR that prevents remote users from doing nasty things to your system (like erase all of your files). The documentation is in BYEZCPR.DOC. INTTERM.MAC INddt putsys.com d01f3,01fb ^< The characters on the right of the above line should read VER 1.4 ^> ^< If they don't, enter a control-C to abort operation and re-read^> ^< the file BYEZCPR.DOC. If you see VER 1.4 , enter a carriage return ^> ^< to continue ^> ^? i10zcpr.hex r3580 ^C save 40 zputsys.com ddt putsys.com d01f3,01fb ^< The characters on the right of the above line should read VER 1.4G ^> ^< If they don't, enter a control-C to abort operation and re-read^> ^< the file BYEZCPR.DOC. If you see VER 1.4G, enter a carriage return ^> ^< to continue ^> ^? i10zcpr.hex r3580 a2096 JMP EB28 . ^C save 40 zputsys.com 3 :10D53C00CD47D6CDA8D6CDE1D5CDDDD53239D6CD9A :10D54C00C4D7C4CFD61167D5D53ABBD7B7C2C9D9C2 :10D55C00CD47D8C2C9D97E23666FE9CDB0D7CDC42B :10D56C00D73A9CD4D62021BBD7B6C2CFD6189ECDE5 :10D57C00C5D54E6F2046696C6580C93E0DCD8ED5E4 :10D58C003E0AC50E025FE5CD0500E1C1C90E01CD15 :10D59C00BED5C33ED6F53E00B72806F1C50E05181C :10D5AC00E4F1F5CD8ED5F1FE0ACA9ED9C9119BD4F2 :10D5BC000E14C5CD0500C1B7C9F5CD87D5F1E3F57E :10D5CC00CDD2D5F1E3C97ECD8ED57E23B7C8F81860 :10D5DC00F50E1918091180000E1A18020E0DC3054C :10D5EC00005F0TTERM.COM XLATETBL.ASM These programs are not really for the remote CP/M system. INTTERM is a replacement for TERM.COM that lets your Kaypro act as a terminal for another system at High Baud rates without dropping characters while scrolling. We added KeyPad and cursor control key translation so that you may emulate any terminal you know the control codes for. The file XLATETBL is an overlay for INTTERM that allows you to reassign key translation values without haveing to reassemble INTTERM. The ins  E0E18F8AF32BBD4119BD40E0FCDCA :10D5FC0005003CC90E1018F7119BD40E1118F00E33 :10D60C001218EC2109D57EB7C83600117AD40E1346 :10D61C0018CC3E005F18021EFF0E2018C1CD23D679 :10D62C00878787872139D6B6320400C93E00320479 :10D63C0000C9FE61D8FE7BD0E65FC93A09D5B72890 :10D64C0045117AD4D5CDF9D5D1283B3A89D43D3280 :10D65C009AD4CDBCD5202F1107D4218000015000C5 :10D66C00EDB02188D436002335117AD4CD00D628DC :10D67C00153E24CD8ED52108D4CDD2D5CDBED6C85D :10D68C00CD0FD6C319D5CD0FD6CD29D63E3ECD8ED6 :10D69C00D50E0A1106D4CD0500C33812CDA1D50600180B3E20CDA1D50478E61A :10D98C000720F5CDBED628B9FE03C818B43DC8C3D0 :10D99C0068DAE521BCD435201036163E00FE50283E :10D9AC0008CD99D5FE03CA67D5E1C9CDC9D65FCDDF :10D9BC0025D6C36AD5CDC9D6328CDA18F53A9CD4A3 :10D9CC00FE2020143ABBD7B7CA6AD53D3239D6CD22 :10D9DC0038D6CDEDD5C36AD53AA4D4FE20C2CFD665 :10D9EC002177D411A4D4010300EDB0210001E5CDC1 :10D9FC006EDAE1C02256DACDB0D7CDC4D721BBD771 :10DA0C00E57E329BD421ABD4CDC7D7E17E32ABD4EB :10DA1C00AF32BBD4115C00219BD4012100EDB021AD :10DA2C0008D47EB72807FE2029D43ABED4B7C9CDF0D6288D :10D81C001C23FE2A2007363FCD3FD818077713FE6E :10D82C003FCC3FD810E6CDF0D6C81318F9233620DC :10D83C0010FBC93ABED43C32BED4C921BFD40E05AC :10D84C00119CD406041ABE200A132310F81AFE20C9 :10D85C002004C92310FD23230D20E50CC93E80F5BF :10D86C00CDC4D7CDA6D7219CD47EFE20CC12D9CD49 :10D87C000DD706002816FE412806FE53200E068002 :10D88C0013ED5359D4FE532803F1AFF5F1571E0095 :10D89C00D57832B9D8CD04D6CC7BD528673D0F0FBF :10D8AC000FE6604F3E0ACD9DD7D1D5A2FE00204A8F :10D8BC00D17B1CD5E603F52005CD87D51808sysgen a | | save 40 cpmzz.com ddt cpmzz.com i2zcpr.hex r2580 ^C sysgen | a | | ^C era cpmzz.com ^<********* ZCPR ++++++++++++++++++++++++> Installed ***********^> D62107D446C1 :10D6AC0004237ECD3ED67710F836002108D42259BB :10D6BC00D4C9D50E0BCDBED5C499D5D1C9CD1FD7E4 :10D6CC00FE10D8CD87D52A5BD47EFE20280BB72838 :10D6DC0008E5CD8ED5E12318F0CDCAD53F80CD0F0E :10D6EC00D6C319D51AB7C8FE2038D8C8FE3DC8FE17 :10D6FC005FC8FE2EC8FE3AC8FE3BC8FE3CC8FE3EC4 :10D70C00C9ED5B59D41AB7C8FE20C01318F7856F42 :10D71C00D024C9CDC4D721A6D4060B7E2BFE202045 :10D72C000410F81804FE48282B219CD40100117E0B :10D73C00FE20281823D630FE0A3013577907070726 :10D74C0081380B8138088238054F10E379C9C3CF73 :108032318F50600111A :10DA3C0081007E12B7280504231318F67832800073 :10DA4C00CD87D5CDE1D5CD29D6CD0001CDE1D5CD34 :10DA5C0038D6CDEDD5C319D5E1CD1ED6CDB0D7C3B3 :10DA6C00CFD6CD77DAF5CD1ED6F1C922A7DACD23E4 :10DA7C00D6321FD6328EDACDA6D7CDF2D5201B3EAC :10DA8C000FFE0F2809328EDA5FCD25D618E921BB9F :10DA9C00D7AFB6C264DA360118DD2100013ED3BC23 :10DAAC003816E5EBCDE4D5119BD4CDBCD5E12006E1 :10DABC001180001918E73DC8CDC5D546756C6C8032 :04DACC003E01B7C997 :0000000000 CDCA3C :10D8CC00D520207C2080060178CD9DD7E67FFE20D8 :10D8DC002013F1F5FE03200B3E09CD9DD7E67FFE0C :10D8EC002028163E20CD8ED50478FE0C300BFE0978 :10D8FC0020D63E2ECD8ED518CFF1CDBED62005CD5F :10D90C000BD61897D1C9060B363F2310FBC93EFF27 :10D91C001801AF32A3D5CDC4D7C2CFD6CD0DD732D7 :10D92C00A8D9280513EB2259D4CDA6D7CDF2D5CA48 :10D93C009BD9CD87D53E1732BCD421BDD436FF063A :10D94C000021BDD47EFE803809E5CDB9D5E1203D5E :10D95C00AF7734218000CD1AD77EE67FFE1AC8FE41 :10D96C000D280EFE0A280AFE09280DCDA1D5041893 :10D97C00D75C00D6CDC4D7219CD4110000060B7EFE202808 :10D76C002DFE482829D63038E5FE0A3806D607FEA5 :10D77C001030DB234F7A07070707E6F0577B0707C4 :10D78C0007075FE60FB2577BE6F0B15F10CEEB7D7B :10D79C00C921800081CD1AD77EC9AF329BD4CDBAB6 :10D7AC00D7C81807CDBAD7C83A39D6C3EDD53E007D :10D7BC00B7C83D2139D6BEC9219BD4AF32BBD7CD1A :10D7CC000DD7ED535BD41AB7280EDE4047131AFE63 :10D7DC003A280BFE3B28071B3A39D67718067832C5 :10D7EC00BBD77013AF32BED40608CD18D80603FED3 :10D7FC002E200613CD18D81803CD39D8060423369D :10D80C000010FBED535  :10E40000C3E1E4C3DDE450002020202020202020B0 :08E41000202020202020200024 :04E4590008E417E4D8 :10E47700434F4D00242424202020202053554200C0 :01E487000094 :10E4BC001600004449522069E84C4953541AE95457 :10E4CC005950451EE955534552B7E944465520C1AC :10E4DC00E9AF3207E43177E4C5791F1F1F1FE60F40 :10E4EC005FCD25E6CDE8E53209E5C179E60F323995 :10E4FC00E62806CDEDE53209E5117AE43E00B72FAA :10E50C00C407E62F3209E53A07E4B720263177E451 :10E51C00CD87E5CDDDE5C641CD8EE5CD23E6FE0A02 :10E52C003809D60AF53E31CD8EE5F1C630CD8EE5F9E43ABEE4B7C9CDF0E6284D :10E81C001C23FE2A2007363FCD3FE818077713FE4E :10E82C003FCC3FE810E6CDF0E6C81318F9233620AC :10E83C0010FBC93ABEE43C32BEE4C921BFE40E056C :10E84C00119CE406041ABE200A132310F81AFE20A9 :10E85C002004C92310FD23230D20E50CC93E80F5AF :10E86C00CDC4E7CDA6E7219CE47EFE20CC12E9CDF9 :10E87C000DE706002816FE412806FE53200E0680E2 :10E88C0013ED5359E4FE532803F1AFF5F1571E0075 :10E89C00D57832B9E8CD04E6CC7BE528673D0F0F7F :10E8AC000FE6604F3E0ACD9DE7D1D5A2FE00204A6F :10E8BC00D17B1CD5E603F52005CD87E51808E62107E44671 :10E6AC0004237ECD3EE67710F836002108E422598B :10E6BC00E4C9D50E0BCDBEE5C499E5D1C9CD1FE794 :10E6CC00FE10D8CD87E52A5BE47EFE20280BB72808 :10E6DC0008E5CD8EE5E12318F0CDCAE53F80CD0FDE :10E6EC00E6C319E51AB7C8FE2038D8C8FE3DC8FEE7 :10E6FC005FC8FE2EC8FE3AC8FE3BC8FE3CC8FE3EB4 :10E70C00C9ED5B59E41AB7C8FE20C01318F7856F22 :10E71C00D024C9CDC4E721A6E4060B7E2BFE202015 :10E72C000410F81804FE48282B219CE40100117EEB :10E73C00FE20281823D630FE0A3013577907070716 :10E74C0081380B8138088238054F10E379C9C3CF63 :108032318F5060011FA :10EA3C0081007E12B7280504231318F67832800063 :10EA4C00CD87E5CDE1E5CD29E6CD0001CDE1E5CDE4 :10EA5C0038E6CDEDE5C319E5E1CD1EE6CDB0E7C353 :10EA6C00CFE6CD77EAF5CD1EE6F1C922A7EACD2394 :10EA7C00E6321FE6328EEACDA6E7CDF2E5201B3E4C :10EA8C000FFE0F2809328EEA5FCD25E618E921BB6F :10EA9C00E7AFB6C264EA360118DD2100013EE3BCE3 :10EAAC003816E5EBCDE4E5119BE4CDBCE5E12006A1 :10EABC001180001918E73DC8CDC5E546756C6C8012 :04EACC003E01B7C987 :0000000000 3 :10E53C00CD47E6CDA8E6CDE1E5CDDDE53239E6CD3A :10E54C00C4E7C4CFE61167E5D53ABBE7B7C2C9E962 :10E55C00CD47E8C2C9E97E23666FE9CDB0E7CDC4EB :10E56C00E73A9CE4D62021BBE7B6C2CFE6189ECD95 :10E57C00C5E54E6F2046696C6580C93E0DCD8EE5B4 :10E58C003E0AC50E025FE5CD0500E1C1C90E01CD05 :10E59C00BEE5C33EE6F53E00B72806F1C50E0518EC :10E5AC00E4F1F5CD8EE5F1FE0ACA9EE9C9119BE4B2 :10E5BC000E14C5CD0500C1B7C9F5CD87E5F1E3F55E :10E5CC00CDD2E5F1E3C97ECD8EE57E23B7C8F81830 :10E5DC00F50E1918091180000E1A18020E0DC3053C :10E5EC00005F0CDCA1C :10E8CC00E520207C2080060178CD9DE7E67FFE20A8 :10E8DC002013F1F5FE03200B3E09CD9DE7E67FFEEC :10E8EC002028163E20CD8EE50478FE0C300BFE0958 :10E8FC0020D63E2ECD8EE518CFF1CDBEE62005CD2F :10E90C000BE61897D1C9060B363F2310FBC93EFF07 :10E91C001801AF32A3E5CDC4E7C2CFE6CD0DE73287 :10E92C00A8E9280513EB2259E4CDA6E7CDF2E5CAF8 :10E93C009BE9CD87E53E1732BCE421BDE436FF06EA :10E94C000021BDE47EFE803809E5CDB9E5E1203D2E :10E95C00AF7734218000CD1AE77EE67FFE1AC8FE21 :10E96C000D280EFE0A280AFE09280DCDA1E5041873 :10E97C00E75C00E6CDC4E7219CE4110000060B7EFE2028C8 :10E76C002DFE482829D63038E5FE0A3806D607FE95 :10E77C001030DB234F7A07070707E6F0577B0707B4 :10E78C0007075FE60FB2577BE6F0B15F10CEEB7D6B :10E79C00C921800081CD1AE77EC9AF329BE4CDBA86 :10E7AC00E7C81807CDBAE7C83A39E6C3EDE53E002D :10E7BC00B7C83D2139E6BEC9219BE4AF32BBE7CDDA :10E7CC000DE7ED535BE41AB7280EDE4047131AFE33 :10E7DC003A280BFE3B28071B3A39E67718067832A5 :10E7EC00BBE77013AF32BEE40608CD18E80603FE93 :10E7FC002E200613CD18E81803CD39E8060423366D :10E80C000010FBED535E0E18F8AF32BBE4119BE40E0FCD9A :10E5FC0005003CC90E1018F7119BE40E1118F00E13 :10E60C001218EC2109E57EB7C83600117AE40E1316 :10E61C0018CC3E005F18021EFF0E2018C1CD23E659 :10E62C00878787872139E6B6320400C93E00320459 :10E63C0000C9FE61D8FE7BD0E65FC93A09E5B72870 :10E64C0045117AE4D5CDF9E5D1283B3A89E43D3240 :10E65C009AE4CDBCE5202F1107E421800001500085 :10E66C00EDB02188E436002335117AE4CD00E6289C :10E67C00153E24CD8EE52108E4CDD2E5CDBEE6C80D :10E68C00CD0FE6C319E5CD0FE6CD29E63E3ECD8E86 :10E69C00E50E0A1106E4CD0500C33812CDA1E50600180B3E20CDA1E50478E6EA :10E98C000720F5CDBEE628B9FE03C818B43DC8C3B0 :10E99C0068EAE521BCE435201036163E00FE50280E :10E9AC0008CD99E5FE03CA67E5E1C9CDC9E65FCD9F :10E9BC0025E6C36AE5CDC9E6328CEA18F53A9CE443 :10E9CC00FE2020143ABBE7B7CA6AE53D3239E6CDE2 :10E9DC0038E6CDEDE5C36AE53AA4E4FE20C2CFE605 :10E9EC002177E411A4E4010300EDB0210001E5CD91 :10E9FC006EEAE1C02256EACDB0E7CDC4E721BBE711 :10EA0C00E57E329BE421ABE4CDC7E7E17E32ABE49B :10EA1C00AF32BBE4115C00219BE4012100EDB0217D :10EA2C0008E47EB72807FE202  :10E00000C3E1E0C3DDE050002020202020202020BC :08E01000202020202020200028 :04E0590008E017E0E4 :10E07700434F4D00242424202020202053554200C4 :01E087000098 :10E0BC001600004449522069E44C4953541AE55463 :10E0CC005950451EE555534552B7E544465520C1B8 :10E0DC00E5AF3207E03177E0C5791F1F1F1FE60F50 :10E0EC005FCD25E2CDE8E13209E1C179E60F3239A5 :10E0FC00E22806CDEDE13209E1117AE03E00B72FBE :10E10C00C407E22F3209E13A07E0B720263177E065 :10E11C00CD87E1CDDDE1C641CD8EE1CD23E2FE0A16 :10E12C003809D60AF53E31CD8EE1F1C630CD8EE1F9E03ABEE0B7C9CDF0E2285D :10E41C001C23FE2A2007363FCD3FE418077713FE56 :10E42C003FCC3FE410E6CDF0E2C81318F9233620B8 :10E43C0010FBC93ABEE03C32BEE0C921BFE00E057C :10E44C00119CE006041ABE200A132310F81AFE20B1 :10E45C002004C92310FD23230D20E50CC93E80F5B3 :10E46C00CDC4E3CDA6E3219CE07EFE20CC12E5CD0D :10E47C000DE306002816FE412806FE53200E0680EA :10E48C0013ED5359E0FE532803F1AFF5F1571E007D :10E49C00D57832B9E4CD04E2CC7BE128673D0F0F8F :10E4AC000FE6604F3E0ACD9DE3D1D5A2FE00204A77 :10E4BC00D17B1CD5E603F52005CD87E11808E22107E04685 :10E2AC0004237ECD3EE27710F836002108E0225997 :10E2BC00E0C9D50E0BCDBEE1C499E1D1C9CD1FE3A8 :10E2CC00FE10D8CD87E12A5BE07EFE20280BB72814 :10E2DC0008E5CD8EE1E12318F0CDCAE13F80CD0FEA :10E2EC00E2C319E11AB7C8FE2038D8C8FE3DC8FEF3 :10E2FC005FC8FE2EC8FE3AC8FE3BC8FE3CC8FE3EB8 :10E30C00C9ED5B59E01AB7C8FE20C01318F7856F2A :10E31C00D024C9CDC4E321A6E0060B7E2BFE202021 :10E32C000410F81804FE48282B219CE00100117EF3 :10E33C00FE20281823D630FE0A301357790707071A :10E34C0081380B8138088238054F10E379C9C3CF67 :108032318F506001102 :10E63C0081007E12B7280504231318F67832800067 :10E64C00CD87E1CDE1E1CD29E2CD0001CDE1E1CDF8 :10E65C0038E2CDEDE1C319E1E1CD1EE2CDB0E3C36B :10E66C00CFE2CD77E6F5CD1EE2F1C922A7E6CD23A8 :10E67C00E2321FE2328EE6CDA6E3CDF2E1201B3E64 :10E68C000FFE0F2809328EE65FCD25E218E921BB7B :10E69C00E3AFB6C264E6360118DD2100013EDFBCF3 :10E6AC003816E5EBCDE4E1119BE0CDBCE1E12006B1 :10E6BC001180001918E73DC8CDC5E146756C6C801A :04E6CC003E01B7C98B :0000000000 F :10E13C00CD47E2CDA8E2CDE1E1CDDDE13239E2CD52 :10E14C00C4E3C4CFE21167E1D53ABBE3B7C2C9E57A :10E15C00CD47E4C2C9E57E23666FE9CDB0E3CDC4FB :10E16C00E33A9CE0D62021BBE3B6C2CFE2189ECDA9 :10E17C00C5E14E6F2046696C6580C93E0DCD8EE1C0 :10E18C003E0AC50E025FE5CD0500E1C1C90E01CD09 :10E19C00BEE1C33EE2F53E00B72806F1C50E0518F8 :10E1AC00E4F1F5CD8EE1F1FE0ACA9EE5C9119BE0C2 :10E1BC000E14C5CD0500C1B7C9F5CD87E1F1E3F566 :10E1CC00CDD2E1F1E3C97ECD8EE17E23B7C8F8183C :10E1DC00F50E1918091180000E1A18020E0DC30540 :10E1EC00005F0CDCA24 :10E4CC00E120207C2080060178CD9DE3E67FFE20B4 :10E4DC002013F1F5FE03200B3E09CD9DE3E67FFEF4 :10E4EC002028163E20CD8EE10478FE0C300BFE0960 :10E4FC0020D63E2ECD8EE118CFF1CDBEE22005CD3B :10E50C000BE21897D1C9060B363F2310FBC93EFF0F :10E51C001801AF32A3E1CDC4E3C2CFE2CD0DE3329B :10E52C00A8E5280513EB2259E0CDA6E3CDF2E1CA0C :10E53C009BE5CD87E13E1732BCE021BDE036FF06FE :10E54C000021BDE07EFE803809E5CDB9E1E1203D3A :10E55C00AF7734218000CD1AE37EE67FFE1AC8FE29 :10E56C000D280EFE0A280AFE09280DCDA1E104187B :10E57C00E35C00E2CDC4E3219CE0110000060B7EFE2028D8 :10E36C002DFE482829D63038E5FE0A3806D607FE99 :10E37C001030DB234F7A07070707E6F0577B0707B8 :10E38C0007075FE60FB2577BE6F0B15F10CEEB7D6F :10E39C00C921800081CD1AE37EC9AF329BE0CDBA92 :10E3AC00E3C81807CDBAE3C83A39E2C3EDE13E0041 :10E3BC00B7C83D2139E2BEC9219BE0AF32BBE3CDEA :10E3CC000DE3ED535BE01AB7280EDE4047131AFE3F :10E3DC003A280BFE3B28071B3A39E27718067832AD :10E3EC00BBE37013AF32BEE00608CD18E40603FEA3 :10E3FC002E200613CD18E41803CD39E40604233679 :10E40C000010FBED535E0E18F8AF32BBE0119BE00E0FCDA6 :10E1FC0005003CC90E1018F7119BE00E1118F00E1B :10E20C001218EC2109E17EB7C83600117AE00E1322 :10E21C0018CC3E005F18021EFF0E2018C1CD23E261 :10E22C00878787872139E2B6320400C93E00320461 :10E23C0000C9FE61D8FE7BD0E65FC93A09E1B72878 :10E24C0045117AE0D5CDF9E1D1283B3A89E03D3250 :10E25C009AE0CDBCE1202F1107E021800001500095 :10E26C00EDB02188E036002335117AE0CD00E228AC :10E27C00153E24CD8EE12108E0CDD2E1CDBEE2C821 :10E28C00CD0FE2C319E1CD0FE2CD29E23E3ECD8E9A :10E29C00E10E0A1106E0CD0500C33812CDA1E10600180B3E20CDA1E10478E6F6 :10E58C000720F5CDBEE228B9FE03C818B43DC8C3B8 :10E59C0068E6E521BCE035201036163E00FE50281A :10E5AC0008CD99E1FE03CA67E1E1C9CDC9E25FCDAF :10E5BC0025E2C36AE1CDC9E2328CE618F53A9CE05B :10E5CC00FE2020143ABBE3B7CA6AE13D3239E2CDF2 :10E5DC0038E2CDEDE1C36AE13AA4E0FE20C2CFE21D :10E5EC002177E011A4E0010300EDB0210001E5CD9D :10E5FC006EE6E1C02256E6CDB0E3CDC4E321BBE329 :10E60C00E57E329BE021ABE0CDC7E3E17E32ABE0AF :10E61C00AF32BBE0115C00219BE0012100EDB02189 :10E62C0008E07EB72807FE202  sysgen a | | save 40 cpmzz.com ddt cpmzz.com i484zcpr.hex r2980 ^C sysgen | a | | ^C era cpmzz.com ^<******** ZCPR +++++++++++++++++++++++> Installed ***********^> ** ; ; ;-------------------------- general options ---------------------------- ; ;*** If you don't know how to do this keep BYELOW=YES ********************* BYELOW: EQU YES ;yes, running BYE3 below CCP; no for above BIOS RAMTOP: EQU 0FFFFH ;last available RAM if BYELOW is 'NO' ; ;************************************************************************** ;*** We only support smart modem with this program if you want to change ** ;*** this you will have to write your own drivers ****************=============================================================== ; ; System equates ; YES: EQU 0FFH ;for conditional assembly NO: EQU 0 ; ; CR: EQU 0DH ;ASCII carriage return LF: EQU 0AH ;ASCII line feed MINUTES: EQU 20*60 ;constant for 1 minute time delay ; IOBYTE: EQU 0003H ;location of CP/M iobyte FCB: EQU 005CH FCBRNO: EQU FCB+32 ; ; ; BDOS equates ; BDOS: EQU 0005H CI: EQU 1 WRCON: EQU 2 DRECTIO: EQU 6 PRINTF: EQU 9 CSTS: EQU 11 OPEN: EQU 15 READ: EQU 20 STDMA: es, chain a .COM file upon carrier reception ;.....next time BYE3 answers the phone. DECIMAL: EQU YES ;yes, decimal value for userlog ; ;*** Dual I/O works very nicely on the kaypro. Typeing at the keyboard is * ;*** is the same as typeing form a remote system. ************************* DUAL$IO: EQU YES ;yes, console/modem linked together ; EXFILE: EQU NO ;yes, chain a .COM file upon loss of carrier ; ;*** See the FKEYS section of this file to see what the keys are defined as ; FKEYS: EQU ********* SMODEM: EQU YES ;yes, for Smartmodem, no for other types ; IOVAL: EQU 0 ;initial value for IOBYTE (only if MINICK 'YES') MINICK: EQU NO ;yes, running MINICBBS OXGATE: EQU NO ;yes, running OXGATE RCPM-BBS system RBBSCK: EQU YES ;yes, running RBBS - sets/resets 'WRTLOC' flag ;----------------------------------------------------------------------- ; ;*** If yes, make sure all these devices are supported by your bios or **** ;*** a remote user could hang your system ******************EQU 26 ; ; ; You will likely also want to change the password, located below at ; label 'PASSWD', and the messages printed at label 'WELCOME' and just ; above label 'HANGUP'. The names of the welcome and .com files are at ; labels 'WELFIN' and 'COMFCB' respectively. (This stuff is near the ; end of this file.) ; ;*********************************************************************** ; ; OPTION CONFIGURATION SECTION ; ;*********************************************************************YES ;yes, local console has special function keys HARDLOG: EQU NO ;yes, echo remote input to printer HOLD: EQU YES ;yes, allows caller to CTL-S the welcome file LGONMSG: EQU NO ;yes, print message before "how many nulls" msg PRINTER: EQU NO ;yes, retain list device PRNTGB: EQU YES ;yes, print "Goodbye..." message PRNTWB: EQU NO ;yes, print a string each time system warm boots PWRQD: EQU NO ;yes, password needed to login ; ;*** See RKEYS section to see what the RKEYs are. ******************* ; BYE3 vKPM (revised 03/14/84) ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ;:: Micro Cornucopia Magazine DmC :: ;:: PO Box 223 Special thanks to Robert Aprato :: ;:: Bend Oregon 97709 who sent us the source code :: ;:: Configuration for Kaypro Earl F. Weener :: ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; ; REMOTE CONSOLE PROGRAM FOR CP/M AND MODEM ; ;========*************** ALLDEV: EQU NO ;yes, retain PUN: RDR: and LST: devices ; BOOTMSG: EQU YES ;yes, print "please wait..." message ; ;*** CallBack is a way for the computer and people to share the same phone* ;*** line. If callback is enabled, to get the computer you call, let the ** ;*** phone ring only once then call back. To get people you let the *** ;*** phone ring more than once. ******************************************* CALLBAK: EQU NO ;yes, allow callback feature ; COMFILE: EQU NO ;y  ****** RKEYS: EQU NO ;yes, remote console has special function keys ; ;*** If set to yes, if no input from user for TOVALUE minutes this system * ;*** disconnects the user. ************************************************ TIMEOUT: EQU YES ;yes, auto logout for sleepy callers TOVALUE: EQU 5 ;minutes to auto logout ; ;*** If yes the number of users is tallied. A control-C on the keyboard *** ;*** displays this number to the sysop. Run BYE by entering BYE /R to *** ;*** reset the counters. ******R: EQU 15 ;user # of WELCOME file WHEEL: EQU 003EH ;location of NZCPR's wheel flag ZILOG: EQU YES ;yes, using a Z-80 or Z-800 ; ; ; If USEZCPR is YES, it automatically sets MAXDRIV and USERMAX from the ; ZCPR locations. Otherwise it uses the vaules you insert for MAXDRV ; and MAXUSR. ; USEZCPR: EQU NO ;yes, if using ZCPR to set max drive and user # MAXDRIV: EQU 003DH ;ZCPR location of MAXDRIV byte MAXUSER: EQU 003FH ;ZCPR location of MAXUSR byte ; ;*** These limit how deep into your system;initial number of nulls LOSER: EQU NO ;yes, warm boot overwrites part of the BIOS ;NO for Kaypro LXID: EQU 11H ;define byte of LXI D,nnnn to fake loader LXIH: EQU 21H ;define byte of LXI H,nnnn to fake loader MHZ: EQU 5 ;processor clock in MHz ; 3 for standard Kaypro ; 4 or 5 for High Speed Kaypro MSGKEY: EQU 'Q'-40H ;(^Q) keycode to print "Message from SYSOP: " MSPEED: EQU 003CH ;baud rate pointer NORING: EQU YES ;yes, UART ring indicator NOT available NZCPR: EQU NO ;yes, ifoverwrites the initial bios jump ; table. This problem was solved for the Superbrain 3.0 bios by find- ; ing a warmboot call to HIGH in the BIOS. This call is then patched by ; BYE. The form of the call is: WBCALL CALL WMSTRT ; IF LOSER WBCALL: EQU 0DE48H ;check this in your BIOS ; ; ; The following location is called ; WMSTRT: EQU EE48H ;check this in your BIOS ENDIF ;LOSER ; ; ;*********************************************************************** ; ; END OF OPTION ******************************************** USRLOG: EQU YES ;yes, count number of users ; ;*** The function must be written by you ********************************** WBRTN: EQU NO ;yes, do function each time system warm boots ; ; ;---------- system and hardware dependent options -------------- ; BLKOUT: EQU YES ;turn off remote send (so that what you enter at ;keyboard is not seen by remote user. BLNKKEY: EQU 'B'-40H ;^B keycode to "blank out" remote terminal (as above) CCSDISK: EQU N a remote user can penetrate. MAXDRV: EQU 2 ;highest drive supported (2=B:) MAXUSR: EQU 15 ;highest user area (set to 0 for CP.M 1.4) ; ;----------------------------------------------------------------------- ; BP110: EQU 0 ;110 bps - baud rate pointers for MSPEED BP300: EQU 1 ;300 bps BP450: EQU 2 ;450 bps BP600: EQU 3 ;600 bps BP710: EQU 4 ;710 bps BP1200: EQU 5 ;1200 bps BP9600: EQU 8 ;9600 bps BP19200: EQU 9 ;19200 bps ; ;---------------------------------------------------------- running NEWZCPR under secure mode ; We are talking about ZCPR-II here. SELPASS: EQU NO ;require a password ; Password is kept near the end of this file SENSE: EQU 0FFH ;sense switch port number SMAXDRV: EQU 16 ;number of drives available to SYSOP SMAXUSR: EQU 16 ;number of user areas available to SYSOP SYSDKEY: EQU 'O'-40H ;(^O) keycode to print "System going down in 5 min.." TWITKEY: EQU 'N'-40H ;(^N) keycode to hangup modem manually WELFILE: EQU YES ;yes, to send a WELCOME file WELUSCONFIGURATION SECTION FOR BYE3 ; ;*********************************************************************** ; ; ORG 100H ; ; ;----------------------- Special Loader Routine ------------------------ ; START: LXI SP,ISTACK ;set stack for initialization routine ; IF BYELOW CALL MDCARCK ;check to see if BYE3 is already loaded LHLD BDOS+1 ;load BDOS vector JZ STARTA ;no carrier, go relocate code INX H ;compute start of BYE3 INX H INX H PCHL ;go execute already loaded code ; STAO ;yes, CCS disk controller CLOSS: EQU 5 ;if carrier dies, wait 5 secs. before hanging up COMUSR: EQU 15 ;user # of .COM file to be called after answer ; (if COMFILE=YES) CPM2: EQU YES ;yes, using CP/M 2.2 CTRLC: EQU 'K'-40H ;map ^C to this if 0000H<>C3H (nb: ^O=15 decimal) CWAIT: EQU 20 ;wait up to 20 seconds for carrier at first EXUSR: EQU 00 ;user # of .COM file to be called upon exit ; (if EXFILE=YES) IMSAI: EQU NO ;yes, if using IMSAI computer with front panel INULLS: EQU 01 ------------- ; IF CCSDISK DISK: EQU 034H ;disk control port DISKON: EQU 071H ;motors on, select disk A: DISKOFF: EQU 051H ;motors off, select disk A: ENDIF ;CCSDISK ; ; ; Assignment of front-panel options to switches: ; IF IMSAI BLACKSW: EQU 04H ;turn on to black out remote end ENABLF: EQU 08H ;turn on to enable special function keys LOGSW: EQU 01H ;turn on for hardcopy PWDSW: EQU 02H ;turn on for 'password' mode ENDIF ;IMSAI ; ; ; There are some cases where warm boot   RTA: LXI D,-(2048+256) ;2k btyes in CCP plus 1 sector DAD D ;make room for the CCP ENDIF ;BYELOW ; IF NOT BYELOW LXI H,RAMTOP-(OBJEND-PEND) ENDIF ;NOT BYELOW ; ; ; HL now contains the destination address of BYE3 ; LXI D,PEND-1 ;set up the source pointer LXI B,PEND-BEGOBJ ;set up byte counter ; ; ; This is the long version for 8080s and 8085s ; IF NOT ZILOG BLOCK: LDAX D ;get program byte MOV M,A ;move program byte MOV A,B ;get byte count ORA C ;finished block tranes-table pointer ; TWOBYT: LDAX D ;get opcode byte from table CMP M ;is this byte a 2-byte opcode? JZ SKIP ;yes, skip it and continue DCR B ;no, end of 2-byte table? INX D ;advance table pointer JNZ TWOBYT ;no, keep looking JMP MODIFY ;yes, it's a one-byte opcode, keep going ; SKIP: INX H ;advance object code pointera JMP MODIFY ;continue search ; CHANGE: LXI D,OBJEND ;set up end of range pointer LXI B,BEGOBJ ;set up beginning of range pointer ; ; ; See if the address is ab new address if it is - otherwise it will ; not disturb the code... ; DCX H ;set up the sourc pointer for the modi- ;..fication routine entry MODIFY: INX H ;point to the next (hopefully) instr. DB LXID ;get the address of the end of BYE3 ; ENDRNG: DW 0 MOV A,E SUB L MOV A,D SBB H ;have we finished moving this block? JC BEGIN ;yes, we can begin now. ; ; ; Here is where we test for the 3-byte opcodes ; MVI B,INST3E-INST3 ;get the number of elements in the table LXI D,INST3make 'HL' totally negative RET ; ; ; Prepare to branch to the bye program ; BEGIN: EQU $ ; IF BYELOW LHLD BDOS+1 PUSH H LXI D,BEGOBJ LHLD OFFSET ;get prgram offset DAD D ;form address of new BDOS address SHLD BDOS+1 ;update BDOS vector INX H POP D MOV M,E INX H MOV M,D INX H ENDIF ;BYELOW ; IF NOT BYELOW LXI D,BEGOBJ2 ;start of BYE3 code LHLD OFFSET DAD D ;'HL' >start of relocated code ENDIF ;NOT BYELOW ; PCHL ;jump to relocated BYE3 program ;sfer? JZ UPDATE ;yes, check on the opcode values DCX D ;no, set source pointer DCX H ;set destination pointer DCX B ;set byte counter JMP BLOCK ;continue block transfer until finished ENDIF ;NOT ZILOG ; ; ; The following is for the Zilog Z-80 or Z-800. ; IF ZILOG XCHG ;reverse source and destination for lddr DB 0EDH,0B8H ;these are the codes for lddr XCHG ;restore regs to original order ENDIF ;ZILOG ; UPDATE: XCHG ;move the source addrress into 'HL' CALL NEGHLove the range ; INX H ;advance pointer to the LSB of the addr MOV A,E SUB M INX H ;advance pointer to the MSB of the addr MOV A,D SBB M JC MODIFY ; ; ; See if the address is below the range ; DCX H ;set back pointer to the LSB of the addr MOV A,M SUB C INX H ;advance pointer to the MSB of the addr MOV A,M SBB B JC MODIFY ; ; ; Update the value of this address by adding the offset to it ; DCX H ;set back pointer to the LSB of the addr DB LXID ;load DE with the o ;set up the 3-byte opcodes table pointer ; THRBYT: LDAX D ;get opcode byte from table CMP M ;is this byte a 3-byte opcode? JZ CHANGE ;change the 2nd and 3rd bytes if needed INX D ;no, advance table pointer DCR B ;end of 3-byte table? JNZ THRBYT ;no, keep looking ; ; ; Skip all the 2-byte opcodes - this keeps the transfer program from ; trying to figure out what the second byte is. ; MVI B,INST2E-INST2 ;get the number of elements in the table LXI D,INST2 ;set up the 2-byte-opcod ; ; The following table defines the 3-byte load instructions used in the ; 8080 instruction set. ; INST3: DB 01H DB 11H DB 21H DB 22H DB 2AH DB 31H DB 32H DB 3AH DB 0C2H DB 0C3H DB 0C4H DB 0CAH DB 0CCH DB 0CDH DB 0D2H DB 0D4H DB 0DAH DB 0DCH DB 0E2H DB 0E4H DB 0EAH DB 0ECH DB 0F2H DB 0F4H DB 0FAH DB 0FCH ; INST3E: EQU $ ;end of 3 byte op codes ; ; The following table is the listing of the 2-byte opcodes used in the ; 8080 instruction code set.  ;prepare value for subtraction DAD D ;form the program offset SHLD OFFSET ;save the program offset XCHG ;set up the offset register LXI H,ENDOBJ ;get the ending addr of the prgm code DAD D ;form new ending addr (new location) SHLD ENDRNG ;save the ending addr of the prgm code LXI H,BEGOBJ ;get the start addr of the program code DAD D ;form new beginning addr (new location) ; ; ; The following code determines whether or not an address is within the ; BYE prgm and sets it to theffset value ; OFFSET: DW 0 MOV A,M ;get base address ADD E ;change LSB to new address MOV M,A ;update memory INX H ;advance pointer to the MSB of the addr MOV A,M ;get the MSB of the base addr ADC D ;change LSB to new address MOV M,A ;update memory JMP MODIFY ;take care of the next instruction ; ; ; Small subroutine to negate the contents of HL ; NEGHL: MOV A,H CMA MOV H,A ;get the complement of the MSB MOV A,L CMA MOV L,A ;get the complement of the LSBb INX H ;  ; INST2: DB 06H DB 0EH DB 16H DB 1EH DB 26H DB 2EH DB 36H DB 3EH DB 0C6H DB 0CEH DB 0D3H DB 0D6H DB 0DBH DB 0DEH DB 0E6H DB 0EEH DB 0F6H DB 0FEH ; INST2E: EQU $ ;end of 2 byte op codes ; ; ; Set aside space for the stack region ; DS 20H ; ISTACK: DW 0 ;top of stack ; ; ;----------------------------------------------------------------------- ; ; THE FOLLOWING CODE GETS MOVED ; TO HIGH RAM BY THE LOADER ; PROGRAM, WHERE IT IS EXECUTED.ate is set to YES. ; COVECT: DW CONOUT ;used by XMODEM programs to find CONOUT DB 'BYE' ;tells XMODEM that BYE3 is being used ; ; ;*********************************************************************** ; ; THIS IS THE OFFICIAL START OF THE BYE PROGRAM ; ;*********************************************************************** ; ; ; If the carrier is lost - hang up, await ring. Otherwise, say goodbye, ; and hang-up. ; START0: EQU $ ;start of the BYE program ; IF BYELOW LHLD BDVAL: DB TOVALUE ; ; ; Number of nulls to put after a carriage return ; NULLS: DB INULLS ; ; ; Upper-case only switch, 32 for uppercase, 0 for upper/lowercase ; ULCSW: DB 0 ; ; ; Line-feed masking bit (non-zero= mask line feeds) ; LFEEDS: DB NO ; ; ; Location RBBS pokes so modem does not hang-up during disk writes ; WRTLOC: DB NO ; ; Switch to let SYSOP turn on/off the hard log (so his work remotely ; will not show up on the hardlog and waste all that paper) if HARDLOG ; is set 'NO', he ; answer mode ; LXI H,FCB+1 ;get first character MOV A,M CPI '/' ;option? JNZ HANGUP ; ; ; Got an option - validate it ; INX H ;get which option it is... MOV A,M STA OPTION ;save it, we might need it later CPI 'A' ;answer immediately? JZ ANSWER ;skip to answer routine ; IF COMFILE CPI 'C' ;answer and do comfile? JZ ANSWER ;skip to answer routine ENDIF ;COMFILE ; IF USRLOG ;check for reset of counters CPI 'R' CZ RESET ENDIF ;USRLOG ; JMP HANGUP ; ;----------------------------------------------------------------------- ; BEGOBJ: JMP 0 ;filled by begin if BYELOW BEGOBJ2:JMP START0 ;hop over fixed vectors ; MCBOOT: JMP MBOOT ;off to warm boot JMP PRNLOG ;go print out items of interest ; ; Variables follow in a predefined order that can be manipulated by a ; passworded or other program to give special users different capabili- ; ties. ; ;*********************************************************************** ; ; Here is a quickieOS+1 ;get beginning address of BYE3 program SHLD BDADDR ;save address of BYE3 start ENDIF ;BYELOW ; XRA A ;a=0 STA LOSTFLG ;show no carrier lost ; IF RKEYS STA BYTEB ;initialize remote key pointers LXI H,0 SHLD BYTEA ENDIF ;RKEYS ; ; ; Set MINICK to 'YES' if you use MINICBBS and want to take advantage of ; its feature which can prevent the modem from hanging up if the caller ; should happen to disconnect during a file update. MINICBBS sets the ; high-order bit of IOBYTthis is ignored, but takes up space so that smart pro- ; grams will not screw stuff up when they change these locations. ; ; HARDON: DB YES ; ; ; LOSTFLAG has been moved up here, so that we can make BYE hang-up the ; the phone without the "good-bye" message (like if we kill a twit). ; LOSTFLG:DB NO ; ; ; Console output vector which points to the "local console" output rou- ; tine. This address is used by external XMODEM programs to set their ; CONOUT address automatically if their USECON equ ;we know it is local, so skip call to ;..carrier check ; ; No option, or invalid one ; NOSLASH:CALL CARCK ;signed off with this program? JC HANGUP ;nobody there ; GOODBY: EQU $ ;Issue good-bye and undo Bios patches ; IF PRNTGB LXI H,GBMSG ;good-bye message CALL ILPRT ;print this message CALL DELAY ;let the good-bye message finishe CALL DELAY ; before calling up BYE3 pgm again ENDIF ;PRNTGB ; CALL UNPATCH ;undo BIOS patches ; ; ; Nobody there, or we are done, so handy reference table to use so we do not get mixed ; up. Please it in any future changes. ; ; |mxusr|mxdrv|toval|nulls|ulcsw|lfeeds|wrtloc|hardon|lostflg|covect| ; |1 byt|1 byt|1 byt|1 byt|1 byt|1 byte|1 byte|1 byte|1 byte |2 byes| ; ;*********************************************************************** ; ; Runtime maximum user area (unused under CP/M 1.4) ; MXUSR: DB MAXUSR ; ; ; Runtime maximum drive available ; MXDRV: DB MAXDRV ; ; ; Number of minutes to wait before timeout ; TOE (address 0003H) to indicate a file update is ; in progress. ; IF MINICK MVI A,IOVAL ;get proper initial value STA IOBYTE ;set it in IOBYTE ENDIF ;MINICK ; ; ; Do not allow a remote user to do 'BYE /A' ; CALL MDCARCK ;call modem carrier check routine JNZ GOODBY ;we have carrier, so say bye bye... ; ; ; Identify version of program ; MVI C,PRINTF ;print function LXI D,VMSG ;signon message CALL BDOS ; ; ; Check for /A option on command - request to go immediately into t   hang up ; HANGUP: LXI SP,STACK ;set up local stack XRA A ;force next warmboot to user 0 STA 0004H ;and drive a: MVI C,14 MOV E,A CALL BDOS MVI A,' ' ;do not allow options STA OPTION ; IF CPM2 AND COMFILE MVI C,32 ;set CP/M user area function MVI E,COMUSR ;location of our COMFILE CALL BDOS ENDIF ;CPM AND COMFILE ; IF COMFILE CALL LODCOM ;load the .COM file ENDIF ;COMFILE ; ; ; Make phone hangup ; HANGUP2:CALL MDINIT ;call modem initialization routine RNG2 ;wait until ring is finished MVI L,45 ;delay 4.5 seconds for next ring ; WAITNX2:CALL DELAY ;wait .1 seconds DCR L ;more to go? JNZ WAITNX2 ;yes, loop CALL MDRING JZ EXPECT ;no?...then is is for me! ; ; ; Call is not for the computer - wait until ringing is done, then reset. ; WAITNR: MVI L,100 ;wait for 10 seconds of silence ; WAITNRL:CALL DELAY ;delay .1 seconds CALL MDRING JNZ WAITNR ;yes, wait 10 more seconds DCR L ;no ring, maybe we're done JNZ WAITNRL ;no, lo;.1 sec delay for debounce CALL MDRING JNZ ENDRING ;wait until ring is finished ENDIF ;NOT NORING ; ; ; This routine minimizes the computer from interfering with the normal ; house hold phone use by having computer users dial, let the phone ring ; once, hang up and then dial again. When the phone rings only once, it ; alerts the computer which then waits for and answers any ring which ; occurs within the next 45 seconds. (This assumes you left the ringer ; connected so you will in fact hgon attempts LXI H,OLDUSR ;get # of attempts CALL BOPLOG ;call routine to add one ENDIF ;USRLOG AND PWRQD ; ANSWERA:CALL MDANSW ;answer phone at 300 bps MVI A,BP300 ;poke in MSPEED value STA MSPEED CALL MDINP ;clear garbage characters CALL MDINP CALL FRSTCR ;check for carrier the first time JC HANGUP2 ;wasn't a voice call ; ; ; Now test input for baud rate - FIRST, check for 300 bps. ; ANSWERB:CALL PATCH ;patch jump table CALL TSTBAUD ;see if bps=300 JZ WELCOME ;yes, ;(will hang up the modem) IF CCSDISK CALL DSKOFF ;turn off drives ENDIF ;CCSDISK ; MVI A,0C3H ;clear any traps left from .COM file STA 0 ; ; ; Await ringing - check local keyboard for CTL-C exit request. Note: ; Must do input via BDOS because CBIOS patches are not done until the ; call comes in. ; RINGWT: CALL UCSTS ANI 7FH ;strip parity bit CPI 'C'-40H ;CTL-C? CZ USRCHK ;check for exit ; IF NORING ;if modem can't check for ring CALL MDCARCK ;check for carrier JNZop some more ENDIF ;(NOT NORING) AND CALLBAK ; IF (NOT NORING) AND CALLBAK AND USRLOG LXI H,NONUSR ;record as a voice call CALL BOPLOG ;call routine to add one ENDIF ;(NOT NORING) AND CALLBAK AND USRLOG ; IF (NOT NORING) AND CALLBAK ;continue w/callback routines JMP HANGUP2 ;go wait for next call ; EXPECT: LXI H,400 ;40 seconds to wait for second call ; RELOOK: CALL MDRING JNZ ANSWER ;yes, go answer it CALL DELAY ;wait .1 second DCX H ;HL=HL-1 MOV A,H ORA L ;is coear it ringing continuously and know it ; is somebody expecting a voice-answer.) ; IF (NOT NORING) AND CALLBAK ;next routines set CALLBAK MVI L,45 ;delay 4.5 seconds for next ring ; WAITNX: CALL DELAY ;wait .1 seconds DCR L ;more to go? JNZ WAITNX ;yes, loop CALL MDRING ;ringing? JZ EXPECT ;no?...it's for me! ; ; ; If second ring, then check for third ring, in case phone exchange the ; caller is using is not synchronized with that of the computer. ; ENDRNG2:CALL MDRING JNZ END exit ; ; ; Now check for 1200 bps ; CALL SET1200 ;now check 1200 bps JNZ ANS1 MVI A,BP1200 ;set the MSPEED pointer STA MSPEED CALL TSTBAUD ;check baud rate JZ WELCOME ; ANS1: EQU $ CALL SET450 ;try 450 bps next JNZ ANS2 MVI A,BP450 ;set MSPEED pointer STA MSPEED CALL TSTBAUD ;check baudrate JZ WELCOME ; ANS2: EQU $ CALL SET600 ;try 600 bps now JNZ ANS3 MVI A,BP600 ;set MSPEED STA MSPEED CALL TSTBAUD ;check baudrate JZ WELCOME ; ANS3: EQU $ CALL SET710 ANSWER ;we have carrier, let's say hello. JMP RINGWT ;nope, loop ENDIF ;NORING ; IF NOT NORING RINGW2: CALL MDRING ;call ring-check routine JZ RINGWT ;not ringing... ; ; ; The phone may be ringing. Wait .1 sec and look again to make sure it ; is not just relay bounce ; CALL DELAY ;.1 sec delay for debounce CALL MDRING ;modem ringing? JZ RINGWT ;no, must have been a relay bounce ; ; ;the phone is definitely ringing, now wait until ring is finished ; ENDRING:CALL DELAY unt zero? JNZ RELOOK ;no, look some more JMP HANGUP2 ;count done, wait for new call ENDIF ;(NOT NORING) AND CALLBACK ; ;------------------- end of callback routines -------------------------- ; ; Modem setup ; ANSWER: EQU $ ;setup the modem ; IF BYELOW CALL BDCHEK ENDIF ;BYELOW ; IF NZCPR ;only when using NEWZCPR w/secure mode XRA A ;when running NZCPR for your CCP. STA WHEEL ;answer the phone in non-wheel mode ENDIF ;NZCPR ; IF USRLOG AND PWRQD;count # of lo   ;try 710 bps (PMMI S-100 modems only) JNZ ANS4 MVI A,BP710 ;set MSPEED STA MSPEED CALL TSTBAUD ;check baudrate JZ WELCOME ; ANS4: EQU $ CALL SET110 ;finally try 110 bps JNZ BADDO ;try again...*sigh* MVI A,BP110 STA MSPEED ;set MSPEED CALL TSTBAUD ;check baudrate JZ WELCOME ; BADDO: CALL UNPATCH ;restore original jump table JMP ANSWERA ;test more - invalid baud rate ; ; ; Get the console status when unpatched ; UCSTS: EQU $ ;get the console status when ; IF CPMSG JMP BDOS ;resume via BDOS after message ; ; ; Here to exit to CP/M, first reset the Smartmodem to default status ; EXCPM: CALL MDQUIT ;return Smartmodem to default settings ; IF CCSDISK CALL DSKON ;turn on the drives ENDIF ;CCSDISK ; MVI A,0FFH STA WHEEL ;restore wheel byte for SYSOP MVI A,SMAXUSR STA MAXUSER ;and MAXUSR MVI A,SMAXDRV STA MAXDRIV ;and MAXDRIV JMP 0000H ;warm boot CP/M ; ; ; BOPLOG increments the 16 bit counter pointer at by HL. If the decimal rogram version number LXI D,VMSG CALL BDOS ; IF USRLOG AND PWRQD ;print # of logon attempts MVI C,PRINTF LXI D,ATMSG CALL BDOS LXI H,OLDUSR+1 ;point to high byte CALL HXOUT ENDIF ;USRLOG AND PWRQD ; IF USRLOG ;print # of logons MVI C,PRINTF LXI D,SUMSG CALL BDOS LXI H,NEWUSR+1 CALL HXOUT ENDIF ;USRLOG ; IF USRLOG AND CALLBAK ;# of voice calls MVI C,PRINTF LXI D,VCMSG CALL BDOS LXI H,NONUSR+1 CALL HXOUT ENDIF ;USRLOG AND CALLBACK ; RET ;if n DAA ACI 40H DAA PUSH B MVI C,02H MOV E,A ;output the number CALL BDOS POP B RET ENDIF ;USRLOG ; ; ; Welcome to the system ; WELCOME:EQU $ ;welcome to the system ; IF CCSDISK CALL DSKON ;turn on the drives ENDIF ;CCSDISK ; IF CPM2 AND NOT USEZCPR MVI A,MAXUSR ;reset maximum user area STA MXUSR STA MAXUSER ENDIF ;CPM2 AND NOT USEZCPR ; IF NOT USEZCPR MVI A,MAXDRV ;reset maximum drive STA MXDRV DCR A STA MAXDRIV ENDIF ;NOT USEZCPR ; X2 MVI C,DRECTIO ;direct I/O call MVI E,0FFH ;ask for input CALL BDOS ;a=0 if no character waiting RET ENDIF ;CPM2 ; IF NOT CPM2 MVI C,CSTS ;in CP/M 1.4, need the status first CALL BDOS ORA A RZ MVI C,CI ;and then the character CALL BDOS RET ENDIF ;NOT CPM2 ;..... ; ; ; Following are the usrlog routines ; IF USRLOG ;reset all logon counters RESET: LXI H,0 ENDIF ;USRLOG ; IF USRLOG AND PWRQD SHLD OLDUSR ;reset attempt counter ENDIF ;USRLOG AND; option is n use, the number is kept as 4 BCD digits. ; IF USRLOG BOPLOG: MOV A,M ;get low byte INR A ;increment ENDIF ;USRLOG ; IF USRLOG AND DECIMAL DAA ;decimal adjust ENDIF ;USRLOG AND DECIMAL ; IF USRLOG MOV M,A ;replace low order byte RNC ;if no carry, bop done INX H ; else carry to high order byte MOV A,M ;get high order byte INR A ; and bop it ENDIF ;USRLOG ; IF USRLOG AND DECIMAL DAA ;decimal adjust ENDIF ;USRLOG AND DECIMAL ; o log, null PRNLOG routine ;..... ; ; USRCHK: CALL PRNLOG ;give info MVI C,PRINTF LXI D,RS1MSG CALL BDOS ;prompt to resume waiting for ring ; PRNREL: CALL UCSTS ;get reply ORA A JZ PRNREL ;wait until answered STA OPTION ;save reply for later CPI 'T' ;is test requested JZ ANSWERB ;go to setup routine CPI 'R' ;is answer "r", for resume? JZ PRNRES ;go do it if so CPI 'R'+20H ;take lower case too JNZ EXCPM ;if not "r", warm boot CP/M ; PRNRES: MVI C,PRINTF LXI D,RS2MRA A ;make sure line feeds are on again STA LFEEDS ; IF TIMEOUT MVI A,TOVALUE ;reset timeout count STA TOVAL ENDIF ;TIMEOUT ; MVI A,2 ;assume this many nulls in case of error STA NULLS ; IF LGONMSG LXI H,LOGMSG ;Logon message CALL ILPRT ;send this message ENDIF ;LGONMSG ; GETNULL:LXI H,NULMSG ;nulls message CALL ILPRT ;send this message CALL MINPUT ;get value MOV C,A ;to 'C' for output CALL MOUTPUT ;echo character MOV A,C ;restore value CPI '0' JC GET PWRQD ; IF USRLOG SHLD NEWUSR ;reset logon counter ENDIF ;USRLOG ; IF USRLOG AND CALLBAK SHLD NONUSR ;reset voice counter ENDIF ;USRLOG AND CALLBACK ; IF USRLOG AND IMSAI MVI A,0FFH OUT SENSE ;reset IMSAI panel display ENDIF ;USRLOG AND IMSAI ; IF USRLOG RET ENDIF ;USRLOG ; ; ; PRNLOG is called to print out the BYE version # and USRLOG info. It ; can be called from outside the program, using the vector after MCBOOT. ; PRNLOG: MVI C,PRINTF ;print out pIF USRLOG MOV M,A ;replace high order byte RET ENDIF ;USRLOG ;..... ; ; IF USRLOG HXOUT: PUSH H ;save pointer CALL HXHAF ;do high order half of # POP H ;restore pointer DCX H ;point to low, then do low half ; HXHAF: MOV A,M ;get half # in a MOV B,A ;save number RAR ;rotate right 4 bits RAR ;to make an ASCII digit RAR RAR CALL ONEOUT ;output MSN to console MOV A,B ;get number back ; ONEOUT: ANI 0FH ;get LSN for output ADI 90H ;convert to decimal ASCII   NULL ;bad, retry CPI '9'+1 JNC GETNULL ;bad, retry SUI '0' ;make binary STA NULLS ;save count ; GETULC: LXI H,CRMSG ;Carriage Return, Line Feed CALL ILPRT ;send this message ; ; ; Print the welcome file ; IF WELFILE LXI H,WELFILN ;source LXI D,FCB ;destination MVI B,13 ;length CALL MOVE ;move the name LXI D,80H ;set DMA address to 80H MVI C,STDMA CALL BDOS ENDIF ;WELFILE ; IF CPM2 AND WELFILE MVI C,32 ;set user number for welcome file MVI E,WELUSR CAMLP ;no, wait for CR ; ; ; Password did not match ; PWNMAT: LXI H,WRGMSG ;wrong password message CALL ILPRT ;send this message DCR D ;more tries? JNZ PASSINP ;yes JMP BADPASS ;no, go hang up ; ; ; Character matched in password ; PWMAT: INX H ;to next character CPI CR ;end? JNZ PWMLP ;no, loop ; ; ; End of password. Any missed chars? ; MOV A,E ;get flag ORA A JNZ PWNMAT ;not right ENDIF ;PWRQD ; NOPASS: EQU $ ; IF USRLOG ;count number of successful login:EQU $ ;get the password ; IF PWRQD AND IMSAI AND SELPASS IN SENSE ;turn the switch up to require password ANI PWDSW JZ NOPASS ENDIF ;PWRQD AND IMSAI AND SELPASS ; IF PWRQD MVI D,3 ;3 tries at password ; PASSINP:LXI H,PWMSG ;password message CALL ILPRT ;send this message LXI H,PASSWD ;point to password MVI E,0 ;no missed letters ; PWMLP: CALL MINPUT ;get a character CPI 60H ;lower case? JC NOTLC ;no, ANI 5FH ;make upper case alpha ; NOTLC: ENDIF ;PWRQD ; empts to read a CR, LF or CTL-C and returns with zero flag ; if the character read is one of these three. ; TSTBAUD:CALL MINPUT ;get character from modem CPI CR ;if a CR RZ CPI LF ;if a LF RZ CPI 'C'-40H ;if a CTL-C RET ;return with proper flags set ;..... ; ; ; Test to see if carrier is there. If after CWAIT seconds, no carrier, ; then return, saying so. This routine is only called just after we as- ; swered the phone. ; FRSTCR: CALL MDCARCK ;carrier there? JNZ CARCK2 ;yeLL BDOS ENDIF ;CPM2 AND WELFILE ; ; ; Open the welcome file ; IF WELFILE LXI D,FCB MVI C,OPEN CALL BDOS ; ; ; Did it exist? ; INR A ;A=> 0 means "no" JZ PASSINT ;no welcome file ; ; ; Got a file, type it ; XRA A ;A=0 STA FCBRNO ;zero record number LXI H,100H ;get initial buffer pointer ; ; ; Type the welcome file ; WELTYLP:CALL RDBYTE ;get a byte CPI 1AH ;EOF? JZ PASSINT ;yes, done MOV C,A ;setup for type CALL MOUTPUT ;type the character CALL MSTAs LXI H,NEWUSR ;get last value CALL BOPLOG ;call routine to add one ENDIF ;USRLOG ; IF IMSAI AND USRLOG LDA NEWUSR ;re-get low order value CMA ;invert for lights OUT SENSE ;display on IMSAI front panel ENDIF ;IMSAI AND USRLOG ; IF BOOTMSG LXI H,PLSMSG ;please wait message CALL ILPRT ;send this message ENDIF ;BOOTMSG ; IF COMFILE AND CPM2 MVI C,32 MVI E,COMUSR ;switch to .COM file user area CALL BDOS ENDIF ;COMFILE AND CPM2 ; IF COMFILE MVI A,20 IF DUAL$IO AND PWRQD PUSH PSW ;save character input CPI 20H ;is character a control code? JNC PWDIS ;pass if displayable MVI C,'^' ;if control map to up arrow then display CALL CONOUT POP PSW PUSH PSW ADI 40H ; PWDIS: MOV C,A CALL CONOUT ;output character locally POP PSW ;restore 'A' reg. ENDIF ;DUAL$IO AND PWRQD ; IF PWRQD CPI 'U'-40H ;CTL-U? JZ PASSINP ;yes, abort, and retry CMP M ;match password? JZ PWMAT MVI E,1 ;no, show miss CPI CR ;CR? JNZ PWs, jump to regular routine PUSH B ;save BC MVI B,CWAIT*10 ;set for "cwait" seconds JMP CARLP ;from here on, same as other routine ; ; ; Loss of connection test ; CARCK: CALL MDCARCK ;carrier there? JNZ CARCK2 ;yep, go onto other checks... PUSH B ;preserve so we can use it MVI B,CLOSS*10 ;set for 'CLOSS' seconds ; CARLP: CALL DELAY ;wait .1 seconds CALL MDCARCK ;check for carrier MOV A,B ;get count back in a POP B ;fix stack in case all is ok JNZ CARCK2 ;got carrier, contT ;check for character typed ORA A JZ WELTYLP ;no, loop CALL MINPUT ;yes, get character ENDIF ;WELFILE ; IF HOLD AND WELFILE CPI 'S'-40H ;CTL-S to delay listing? JNZ WELTYLP ;no, loop until EOF ; WAIT: CALL MSTAT ORA A ;has another char been typed? JZ WAIT ;no, wait CALL MINPUT ;yes, check character ENDIF ;HOLD AND WELFILE ; IF WELFILE CPI 'C'-40H ;CTL-C to end listing? JNZ WELTYLP ;no, loop until eof ENDIF ;WELFILE ; ; ; Get the password ; PASSINTH ;fool the system so that the .COM file STA FCB+1 ; will see a space at FCB+1 for default LDA OPTION ; purposes. CPI 'A' ;SYSOP can bypass .COM file by typing JZ 0000H ; BYE /A CPI 'C' ;SYSOP can also go to .COM file loaded JNZ RUNCOM ; with BYE /C LXI H,LSMSG ;loading System Message CALL ILPRT ;send this message: CALL LODCOM ; ; ; Everyone else gets com file ; RUNCOM: CALL 100H ENDIF ;COMFILE ; JMP 0000H ;warm boot now for "normal" CP/M use ; ; ; TSTBAUD att  inue on DCR A ;count time down STC ;in case this is the end of 'time' RZ ;return if timed out PUSH B ;preserve 'BC' MOV B,A ;get counter value in 'B' JMP CARLP ;keep checking ; ; ; Now test drive #'s and (if CP/M 2.x) user #'s to insure that maximums ; are not exceeded. ; CARCK2: EQU $ ; IF USEZCPR LDA MAXDRIV INR A STA MXDRV LDA MAXUSER STA MXUSR ENDIF ;USEZCPR ; IF NOT USEZCPR LDA MXDRV DCR A STA MAXDRIV LDA MXUSR STA MAXUSER ENDIF ;NOT USEZCip to cold boot DCX H DCX H ; IF (NOT PRINTER) AND (NOT ALLDEV) MVI B,18 ;# of bytes to move ENDIF ;(NOT PRINTER) AND (NOT ALLDEV) ; IF PRINTER ;retain list device? MVI B,15 ;don't move lister jump ENDIF ;PRINTER ; IF ALLDEV ;this patches all devices to phone MVI B,24 ;move all jumps ENDIF ;ALLDEV ; RET ;..... ; ; ; Move (HL) to (DE), length in (B) ; MOVE: MOV A,M ;get a byte STAX D ;put at new home INX D ;bump pointers INX H DCR B ;decrement byz ; DELAY1: DCX B MOV A,B ORA C JNZ DELAY1 POP B RET ;..... ; ; ; 50 milliseconds delay routine ; KDELAY: PUSH B LXI B,2083*MHZ JMP DELAY1 ; ; ; Patch in the new JMP table (saving the old) ; ; PATCH: CALL TBLADDR ;HL= CP/M BIOS jump table LXI D,VCOLDBT ;point to save location MVI B,24 ;save all vectors CALL MOVE ;move it LHLD VCONOUT+1 ;get the original CONOUT address SHLD COVECT ;store for use with XMODEM programs ; ; ; Now move the new JMP table to CP/M ; CA STA LOSTFLG ; IF EXFILE MVI C,32 MVI E,EXUSR ;switch to exit .COM file user area CALL BDOS CALL LODEX CPI '*' ;test that file was really loaded JNZ 100H ;EXITFIL was't loaded, so run it ENDIF ;EXFILE ; CALL UNPATCH JMP HANGUP ; ; ; Readbyte routine - used to read the welcome file ; IF WELFILE RDBYTE: MOV A,H ;time to read? ORA A ;if at 100H, no read required JZ NORD ; ; ; Have to read a sector ; LXI D,FCB MVI C,READ CALL BDOS ORA A ;ok? MVI A,1AH PR ; LDA 0004H ;check disk/user # ANI 0FH ;isolate drive PUSH H ;save 'HL' LXI H,MXDRV ;point to allowed # of drives CMP M ;valid drive? JC CARCK3 ;yes, skip this junk LDA 0004H ;get whole login byte ANI 0F0H ;retain user # & force drive to A: STA 0004H ;update login byte LXI H,IDMSG ;Incorrect Drive Message CALL ILPRT ;tell user what he did JMP 0000H ;warm boot ;..... ; ; CARCK3: EQU $ ; IF CPM2 LDA 0004H ;get login byte ANI 0F0H ;isolate user # RRC ;mte count JNZ MOVE ;if more, do it RET ;if not, return ;..... ; ; IF LOSER NWBCALL:CALL WMSTRT ;warm boot disk read CALL PATCH ;fix BIOS again after WMSTRT RET ENDIF ;LOSER ;..... ; ; ; Common routine to check for carrier lost - called from console out ; CHECK: EQU $ ;check for carrier lost ; IF MINICK LDA IOBYTE ;get IOBYTE ANI 80H ;test for disk update RET ;busy, wait until done ENDIF ;MINICK ; IF RBBSCK LDA WRTLOC ;get write in progress flag ORA LL TBLADDR ;HL= CP/M BIOS jump table XCHG ;move it to 'DE' LXI H,NEWJTBL ;point to new jump table CALL MOVE ;move it RET ;..... ; ; UNPATCH:CALL TBLADDR ;HL= CP/M BIOS jump table XCHG ;move to DE LXI H,VCOLDBT ;get saved table CALL MOVE ;move original table back ; IF LOSER LXI H,WMSTRT ;load old call location SHLD WBCALL+1 ;restore old call ENDIF ;LOSER ; RET ;..... ; ; ; Calculate HL=CP/M's jump table, B=length ; TBLADDR:LHLD 1 ;get BIOS pointer DCX H ;sk ;fake up EOF RNZ ;return EOF if bad LXI H,80H ; NORD: MOV A,M ;get character INX H ;point to next byte RET ENDIF ;WELFILE ; ; ; Keyboard/modem status test routine ; MSTAT: EQU $ ; IF BYELOW CALL BDCHEK ;if BYELOW, set 6 to safety ENDIF ;BYELOW ; CALL CHECK ;check for carrier lost ; IF DUAL$IO ;want local console? CALL CONSTAT ;get local status ORA A RNZ ;return if local character ENDIF ;DUAL$IO ; CALL MDINST ;get modem input status RET ;....ove to low bits RRC RRC RRC LXI H,MXUSR ;point to maximum user number CMP M ;valid user #? JC CARCK4 ;yes, don't change JZ CARCK4 LDA 0004H ;get login byte again ANI 0FH ;keep drive, zero user area STA 0004H ;update login byte LXI H,IUMSG ;Invalid User message CALL ILPRT ;tell him what happened JMP 0 ;warm boot ENDIF ;CPM2 ; CARCK4: POP H ;restore 'HL' ORA A RET ;..... ; ; ; .1 sec delay routine ; DELAY: PUSH B LXI B,4167*MHZ ;timing constant * clock MHA RNZ ;busy, wait until done ENDIF ;RBBSCK ; CALL CARCK ;see if carrier still on RNC ;all ok ; ; ; Carrier is lost. Type message so local console shows the reason. ; Come come here on bad password. ; BADPASS:MVI A,1 ;show carrier lost - do not check again STA LOSTFLG LXI SP,STACK ;ensure valid stack LXI H,CLMSG ;carrier lost message CALL ILPRT ;Send this Message ; DROPCAR:LXI SP,STACK CALL UNPATCH ;restore original BIOS jump table XRA A ;clear out carrier lost flag  . ; ; ; Modem input function, checks local console first ; MINPUT: EQU $ ; IF BYELOW CALL BDCHEK ENDIF ;BYELOW ; IF RKEYS LDA BYTEB ORA A JNZ CAP ENDIF ;RKEYS ; IF TIMEOUT LDA TOVAL ;get # of minutes before timeout ; MINPUT0:STA TOCNTM ;set minutes counter PUSH H LXI H,MINUTES ;init one minute timeout counter SHLD TOCNT POP H ENDIF ;TIMEOUT ; MINPUT1:LDA LOSTFLG ;known loss of carrier? ORA A CZ CHECK ;carrier still on? CALL MSTAT ;anything? output function ; MOUTPUT:EQU $ ; IF BYELOW CALL BDCHEK ENDIF ;BYELOW ; ; ; If we already know carrier is lost, do not check for it again or loop ; trying to output. ; LDA LOSTFLG ;known loss of carrier? ORA A JNZ SILENT ;avoid loop in case carrier lost CALL CHECK ;carrier still on? ; MOUTA: CALL MDOUTST ;check modem output status JZ MOUTA MOV A,C ;get character ANI 7FH ;strip parity bit ; IF OXGATE CPI 60H ;check for lower case JC MOUTP2 ;skip if not lower  ;echo on printer CPI CR JNZ NOLOG ;return needs linefeed MVI A,LF CALL LISTOUT ;so send it MVI A,CR ;get back CR ENDIF ;HARDLOG ; NOLOG: IF RKEYS PUSH H PUSH D PUSH B PUSH PSW CPI ' ' JNC NOLOG2 MOV E,A ;save char ADD E ;A*3 (3 bytes per table entry) ADD E MOV E,A MVI D,0 LXI H,TABLE DAD D INX H ;increment past dummy jump op code MOV E,M INX H MOV D,M XCHG MOV A,H ORA L JZ NOLOG2 SHLD BYTEA MVI A,1 STA BYTEB POP PSW POP B POP D  RET ;..... ; ; ; Boot trap - becomes disconnect if JMP at 0 has been altered ; MBOOT: LDA 0 ;look at opcode CPI 0C3H ;is it still a jmp? JNZ NOSLASH ;no, so say bye bye... ; ; ; Special warm-boot routine - print a message or something - even run a ; program if you want to!!! ; WMBMSGPRT:EQU $ ; IF WBRTN PUSH B PUSH D PUSH H ; IF PRNTWB LXI H,WBMSG CALL ILPRT ;print the following message: ENDIF ;PRNTWB ; POP H POP D POP B ENDIF ;WBRTN ; JMP VWARMBT ORA A ; IF NOT TIMEOUT JZ MINPUT ;loop til character received ENDIF ;NOT TIMEOUT ; IF TIMEOUT JNZ MINPUT2 CALL KDELAY ;wait 50 ms PUSH H LHLD TOCNT ;knock down timeout counter DCX H SHLD TOCNT MOV A,H ORA L POP H JNZ MINPUT1 ;still time left, keep trying LDA TOCNTM ;count off last minute DCR A JNZ MINPUT0 ;go back if time left LXI H,ITOMSG CALL ILPRT JMP NOSLASH ENDIF ;TIMEOUT ; MINPUT2: IF DUAL$IO ;both local and remote CALL CONSTAT ;check loccase CPI 7FH ;check for rubout JZ MOUTP2 PUSH H LXI H,ULCSW ;subtract either 20H or nothing SUB M POP H MOV C,A ;force on local as well as remote ; MOUTP2: CPI LF ;we have a toggle for line feeds JNZ MOUTP3 ;nope, not a LF LDA LFEEDS ;yes, see if we can send it... ORA A ;set flags MVI A,0 ;prepare with a null JNZ MOUTP3 ;nope, don't (instead, send a null) MVI A,LF ;yes, it's ok to send the line feed ; MOUTP3: ENDIF ;OXGATE ; CALL MDOUTP ;output character to mod POP H ; CAP: PUSH H PUSH D PUSH B LHLD BYTEA MOV A,M INX H SHLD BYTEA ORA A JNZ NL2 XRA A STA BYTEB POP B POP D POP H JMP MINPUT ; NL2: POP B POP D POP H JMP NL22 ; NOLOG2: POP PSW POP B POP D POP H ; NL22: ENDIF ;RKEYS CPI 3 ;is it ^c? RNZ ;no, pass it through LDA 0 ;see if warm boot disabled CPI 0C3H ;jump means warm boot ok MVI A,3 ;so return with a ^C RZ MVI A,CTRLC ;else convert to different character RET ;..... ; ; ; Modem  ;go do a warm boot ;..... ; ; ; Inline print routine ; ; The following code has been modified to accomodate the automatic ; loader. (The loader may modify a constant, so all messages have ; been placed at the end of the program and just moved to high memory.) ; ILPRT: PUSH B ;save BC ; ILPLP: MOV C,M ;get character CALL MOUTPUT ;output it INX H ;point to next character MOV A,M ;test for end of message ORA A JNZ ILPLP POP B ;restore BC RET ;return past message ;..... ; al console ORA A ;character? JNZ CONIN ;yes, read it & return ENDIF ;DUAL$IO ; ; ; Local console wasn't ready, so read modem ; CALL MDINP ANI 7FH ;delete parity JZ MINPUT ;ignore nulls ; IF HARDLOG PUSH B MOV B,A ;put a copy of the character in b LDA HARDON ;if HARDON=0 then turn HARDLOG off (so ORA A ;..SYSOP does not waste paper while he MOV A,B ;..playing ZORK from work.) POP B JZ NOLOG ; CPI 20H JNC MINPUT3 CPI CR JNZ NOLOG ; MINPUT3:CALL LISTOUT em ; SILENT: EQU $ ; IF DUAL$IO ;to local console too? PUSH PSW ;save character CALL CONOUT ;send to regualr BIOS POP PSW ;get character again ENDIF ;DUAL$IO ; ; ; Check for nulls ; CPI LF ;time for nulls? RNZ ;no, return ; ; ; Send nulls if required ; LDA NULLS ;get count ORA A ;any? RZ ;no PUSH B MOV B,A ;save count MVI C,0 ;0 is a null ; NULLP: CALL MOUTPUT ;type a null DCR B ;another? JNZ NULLP ;yes, loop POP B MVI C,LF ;now, send a LF   ; ; Routine to load the com file ; LODCOM: EQU $ ;routine to load the .COM file ; IF COMFILE LXI H,COMFCB SHLD CURRFCB XRA A ;initialize FCB STA COMFCB LXI H,COMFCB+12 MVI B,21 CALL ZLOOP LXI D,COMFCB CALL OPENFIL JZ ABORT JMP LOADFIL ENDIF ;COMFILE ; LODEX: IF EXFILE LXI H,EXFCB SHLD CURRFCB LXI H,EXFCB+12 MVI B,21 CALL ZLOOP LXI D,EXFCB CALL OPENFIL MVI A,'*' ;do not try to run unloaded file RZ ;cannot open file, finish BYE hangup ENDIF ;EXF ANI ENABLF ;check function key enable switch MOV A,B ;get character POP B RZ ;no function key if switch off ENDIF ;FKEYS AND IMSAI ; IF FKEYS CPI BLNKKEY ;turn off caller's output for a moment? JZ BLNKTOG ;(this is a toggle) CPI SYSDKEY JZ SYSDOWN ;tell caller to leave in 5 minutes CPI TWITKEY JZ DROPCAR ;hang up on the twit CPI MSGKEY RNZ LXI H,MFSMSG ;SYSOP message CALL ILPRT ;tell caller you want to say something MVI A,' ' RET ;..... ; ; SYSDOWN:LXI H ABORT ;we should have read something LXI D,80H ;we did, reset DMA to 80H MVI C,STDMA CALL BDOS LXI D,CFLMSG LDA OPTION ;see if this was "BYE /C" CPI 'C' ;if yes, do not print message RZ MVI C,PRINTF CALL BDOS RET ;..... ; ; ZLOOP: MVI M,0 INX H DCR B JNZ ZLOOP RET ;..... ; ; OPENFIL:MVI C,OPEN ;open file pointed to by 'DE' CALL BDOS INR A RET ;..... ; ; ABORT: LXI D,CNFMSG ; ERRXIT: MVI C,PRINTF CALL BDOS ;print the abort message JMP EXCPM ;warm boopied on top of the one pointed to by ; location 1 in CP/M. ; NEWJTBL:JMP MCBOOT ;cold boot JMP MBOOT ;warm boot JMP MSTAT ;modem status test JMP MINPUT ;modem input routine JMP MOUTPUT ;modem output routine ; IF NOT ALLDEV RET ;dummy list device NOP NOP ENDIF ;NOT ALLDEV ; IF ALLDEV JMP MOUTPUT ;modem list device JMP MOUTPUT ;modem punch device JMP MINPUT ;modem reader device ENDIF ;ALLDEV ; IF CCSDISK DSKON: PUSH PSW ;save 'A' and flags MVI A,DISKILE ; ; ; Now load the file ; IF COMFILE OR EXFILE LOADFIL:LHLD 6 ;get top of memory LXI D,-80H DAD D PUSH H ;save on stack LXI D,80H ;TPA-80H LXI B,0 ;keep a record counter PUSH B ;save counter PUSH D ;and load address ; GLOOP: POP D ;get TPA address LXI H,80H ;point to next address to read to DAD D ;HL has the address POP B ;increment the counter ; ; ; Check for load past top-of-memory ; POP D ;get (top-of-memory) PUSH D ;resave for next time MOV A,E ;s,SGDMSG ;system going down message CALL ILPRT ;send this message MVI A,' ' RET ;..... ; ; BLNKTOG:LDA LOSTFLG ORA A ;if zero, make 0FFH MVI A,0FFH ;(we do not use CMA, because LOSTFLG JZ BLNKT1 ; could equal a different value like 1) XRA A ;if not zero, make it zero ; BLNKT1: STA LOSTFLG MVI A,' ' RET ; ENDIF ;FKEYS ;..... ; ; CONOUT: PUSH B PUSH D PUSH H CALL VCONOUT POP H POP D POP B RET ;..... ; ; LISTOUT:PUSH B PUSH D PUSH H PUSH PSW ; ot ENDIF ;COMFILE OR EXFFILE ; ; ; This area is used for vectoring calls to the user's CBIOS, but saving ; the registers first in case they are destroyed. ; CONSTAT:PUSH B PUSH D PUSH H CALL VCONSTAT POP H POP D POP B RET ;..... ; ; CONIN: PUSH B PUSH D PUSH H CALL VCONIN ; IF FKEYS CALL CKFUNC ENDIF ;FKEYS ; POP H POP D POP B RET ;..... ; ; CKFUNC: IF FKEYS AND IMSAI PUSH B MOV B,A ;save character IN SENSE ;read the switches (tea leaves?) ON ;turn on motors OUT DISK PUSH H ;now, wait a long time LXI H,0000K ; DSKLP: XTHL XTHL DCX H ;count loop MOV A,H ;check if done? ORA L JNZ DSKLP POP H ;restore HL POP PSW ;and 'A' and flags RET ; DSKOFF: PUSH PSW ;save 'A' and flags MVI A,DISKOFF ;turn motors off OUT DISK POP PSW RET ENDIF ;CCSDISK ;..... ; ; ; The 'JMP' instructions in the remote control keys are necesary for the ; relocation routines to relocate the address. ; IF RKEYS TABLE: JMP 0 ubtract: (top) - (address) SUB L MOV A,D ;only the carry needed SBB H JNC SIZEOK ;CY=better MOVCPM LXI D,PTSMSG JMP ERRXIT ; SIZEOK: INX B PUSH B PUSH H ;save TPA address XCHG ;align registers MVI C,STDMA ;tell BDOS where to put record CALL BDOS LHLD CURRFCB ;point to aprropriate FCB XCHG MVI C,READ CALL BDOS ORA A JZ GLOOP ;a=0 if more to read POP B ;unjunk stack POP B ;this is our counter POP H ;more junk on stack MOV A,B ;check for zero ORA C JZIF BYELOW CALL BDCHEK ENDIF ;BYELOW ; MOV C,A CALL VLISTOUT POP PSW POP H POP D POP B RET ;..... ; ; IF BYELOW BDCHEK: PUSH H ;to make truly universal, (???) this DB LXIH ; program always re-stores the BDOS ; BDADDR: DW 0000H ; pointer at 6&7 set up location for SHLD 6 ; beginning address of CONSOLX CTL ; at every chance. This replaces the POP H ; WMLOCK & OLDBD as in BYE2 AND BYE3 RET ENDIF ;BYELOW ;..... ; ; ; This is the jmp table which is c   JMP DIR ;^A JMP DIR2 ;^B JMP 0 JMP 0 JMP 0 JMP FIND ;^F JMP GBYE ;^G JMP 0 JMP 0 JMP 0 JMP 0 JMP LTYPE ;^L JMP 0 JMP 0 JMP 0 JMP 0 JMP 0 JMP RBBS ;^R JMP 0 JMP TYPE ;^T JMP 0 JMP 0 JMP NEW ;^W JMP 0 JMP LCRCK ;^Y JMP CRCK ;^Z JMP XMDM ;^[ JMP 0 JMP LDIR ;^] JMP CHAT ;^^ JMP 0 ENDIF ;RKEYS ;..... ; ; ;*********************************************************************** ; ; $$$$ Smartmodem insert for BYE3 - 01/01/84 $ ; SMSEND: XTHL ;save HL, get address of message CALL DLP ;allow modem to stabilize PUSH B ;save 'BC' registers ; SMPLP: CALL MDOUTST ;modem ready for character? JZ SMPLP ;no, go check again MOV A,M ;get the character OUT DPORT ;Send the character INX H ;point to next MOV A,M ;Get next character ORA A ;Has all been sent JNZ SMPLP ;no, go send another character POP B ;restore the BC registers XTHL RET ;return past end of message ;..... ; ; ENDIF ;SMODEM ; S0: This is the number of times the phone can ring before ; the SmartModem answers. A value of 0 means "do not ; answer." Once you are ready to receive, S0=2 will ; let it answer on the second ring. ;..... ; ; ; Delay about two seconds to let modem get stabilized before or after a ; command string. ; DLP: MVI B,20 ;wait about two seconds to "be sure" ; DLP1: CALL DELAY DCR B JNZ DLP1 RET ;..... ; ; ; (This routine is not needed with the current SMINIT routine.) ; SMANSW: RET  option for alt. CTC baud set format. - Paul Traina ; 02/21/83 Initial version. - Steve Fox ; ;----------------------------------------------------------------------- ; ; ; Set base port for SIO & CTC chips ; BASEP: EQU 4H ;Base port for SIO BASEC: EQU 18H ;Base port for CTC baud rate generator ; ; ; The following define the port addresses to use. ; DPORT: EQU BASEP ;Data port SPORT: EQU BASEP+2 ;Status/Control port BPORT: EQU BASEC ;Baud rate port ; ; ; The following are SPORT $$$ ; IF SMODEM ; ; SWITCH SETTINGS: 1 2 3 4 5 6 7 8 ; ; HAYES Smartmodem 300/1200 -- UP UP DN UP DN UP UP DN ; US Robotics Auto-Dial 212 -- UP UP UP UP ; ; ; The following routines are patterned after work originally done by Don ; Brown. ; ; Initialize the Smartmodem. First, disable the auto-answer to prevent ; any problems if somebody phones while you are resetting the registers. ; Then reset the registers for normal unattended operation. ; SMINIT: CALL SET300 ;program com; End of Smartmodem insert ;*********************************************************************** ; ; ++++ INSTALL YOUR MODEM CONTROL PATCHES HERE ++++ ; ;*********************************************************************** ; ; Zilog Z80-SIO routines ; Version 1.6 by Steve Fox & Paul Traina ; ; These routines will allow the easy patching of BYE3 for any type of ; modem/serial port combination. Certain routines must return status ; flags, so please be careful to set the flags a CALL SMSEND ;send following message to modem DB 'A',CR,0 ;answers the phone RET ;..... ; ; ; DE-INITIALIZE THE SMARTMODEM ; ; When the operator uses CTL-C followed by anything but "R", this call ; will drop the 'AA' and return the Smartmodem to default settings. ; SMQUIT: CALL SMSEND ;send following message to modem DB 'AT Z',CR,0 ;reset modem to standard default CALL DLP ;insure command line is completed RET ;..... ; ; ; Send a command string to the Smartmodem (similar to ILPRT) commands (output these to SPORT) ; RESCHN: EQU 00011000B ;Reset channel RESSTA: EQU 00010000B ;Reset ext/status WRREG1: EQU 00000000B ;Value to write to register 1 WRREG3: EQU 11000001B ;8 bits/char, Rx enable WRREG4: EQU 01000100B ;16x, 1 stop bit, no parity DTROFF: EQU 00000000B ;DTR off, RTS off DTRON: EQU 11101010B ;DTR on, 8 bits/char, Tx enable, RTS on ONINS: EQU 00110000B ;Error reset ; ; ; The following are SPORT status masks ; DAV: EQU 00000001B ;Data available TBMT: EQU 00000100B ;Tmences looking for 300 bps CALL SMSEND ;go send smartmodem reset DB 'AT Z',CR,0 ;reset modem to standard default CALL SMSEND ;go initialize the modem DB 'AT Q1 E0 M0 S2=128 S0=2',CR,0 CALL DLP ;delay routine RET ;... ; ; ; Actually, the above string can vary somewhat (e.g. you may want to ; leave the speaker on, you may want to inhibit codes/text, etc. Those ; items are all optional. ; ; ; E0: Do not echo characters in command state ; ; M0: Do not turn the loud speaker on ; ; s directed. ; ; This version is for the Zilog SIO chip that is hooked up to an extern- ; al modem. A Z80-CTC is used as the baud rate generator. ; ;----------------------------------------------------------------------- ; ; 11/27/83 Altered and renamed to work with BYE3 - Irv Hoff ; 08/04/83 Updated for use with ByeII version 1.6 - Paul Traina ; 07/19/83 Improved operation of modem initialization. - Paul Traina ; 04/18/83 Added option to use 300/1200 Smartmodem. - Don Brown ; 04/14/83 Added  ransmit buffer empty DCD: EQU 00001000B ;Data carrier detect PE: EQU 00010000B ;Parity error OE: EQU 00100000B ;Overrun error FE: EQU 01000000B ;Framing error ERR: EQU PE+OE+FE ;Parity, overrun and framing error ; ; ; First Byte of CTC Command: ; BDCMD1: EQU 00H ;110 baud (timer mode) BDCMD2: EQU 40H ;300, 600 & 1200 baud (counter mode) ; ; ; The following are baud rates for BPORT -- they will have to be changed ; for your particular CTC. ; BD300: EQU 05H ;300 bps ;BD600: EQU 64 ;600 re is no carrier, it will return with the Zero flag set. ; MDCARCK:MVI A,RESSTA ;Reset status OUT SPORT IN SPORT ;Get status ANI DCD ;Check for data carrier RET ;Return ; ; ; The following routine determines if there is a character waiting to ; be received. If no character is waiting, the Zero flag will be set, ; otherwise, 255 will be returned in register A. ; MDINST: IN SPORT ;Get status ANI DAV ;Got a character? RZ ;Return if none ORI 0FFh ;..Otherwise, set the proper flae receive register OUT SPORT MVI A,5 ;Setup to write register 5 OUT SPORT MVI A,DTRON ;turn on DTR so modem can answer phone OUT SPORT ; IF SMODEM ;If using Hayes 300/1200 Smartmodem CALL SET300 ;make sure we are at 300 baud CALL SMINIT ;go initialize Smartmodem now ENDIF ;SMODEM ; RET ;Return ;..... ; ; ; The following routine will turn off DTR and the whole mess. It will ; also tell the Smartmodem to stop answering calls. ; MDQUIT: IF SMODEM ;if using a Smartmodef the baud rate change was successful, make ; SURE the Zero flag is set. ; ; ; Set up for 300 bps ; SET300: MVI A,BD300 ;Load rate ; PUSH PSW ;..store it ; MVI A,BDCMD1 ;Get first byte of command JMP SETBAUD ;..... ; ; ; Set up for 1200 bps ; SET1200:MVI A,BD1200 ;Load rate ; PUSH PSW ;..save it ; MVI A,BDCMD2 ;Get first byte of command JMP SETBAUD ;..... ; ; SETBAUD:OUT BDCMD1 ;Send first byte of command ; POP PSW ;Restore the rate ; OUT BPORT ;Send rate XRA A ;Say rate bps (not supported by Smartmodem) BD1200: EQU 07H ;1200 bps ; ; ;*********************************************************************** ; ; If any of your routines zap anything other than the Accumulator, then ; you must preserve all other registers. ; ;*********************************************************************** ; ; This routine should turn off everything on the modem, hang it up, and ; get it ready to wait for a ring. ; MDINIT: MVI A,RESCHN ;Reset channel OUT SPORT MVI A,4 g RET ;...and return ;..... ; ; ; The following is a routine that will input one character from the ; modem port. If there is nothing there, it will return garbage... so ; use the MDINST routine first. ; MDINP: IN DPORT ;Get character ANI 7FH ;Strip parity RET ;Return ;..... ; ; ; The following is a routine to determine if the transmit buffer is ; empty. If it is empty, it will return with the Zero flag clear. If ; the transmitter is busy, then it will return with the Zero flag m CALL SMQUIT ;tell it to shut down ENDIF ;MDQUIT ; MVI A,5 ;Setup to write register 5 OUT SPORT MVI A,DTROFF ;Clear DTR causing shutdown OUT SPORT RET ;..... ; ; ; The following routine will reset the CTC to 300 baud and allow the ; modem to answer the phone when DTR is set True. ; MDANSW: CALL SET300 ;Set 300 baud IN DPORT ;Clear out garbage IN DPORT ;Make sure we're clear RET ;Return ; ; ; The following routine checks to make sure we still have carrier. If ; theis OK RET ;Return ;..... ; ; ; The following routine returns a 255 because we were not able to set to ; the proper baud rate because either the serial port or the modem can't ; handle it. ; SET110: DS 0 ;110 baud not supported SET450: DS 0 ;450 baud not supported SET600: DS 0 ;600 baud not supported SET710: DS 0 ;710 baud not supported ; SETINV: ORI 0FFH ;Make sure zero flag is not set RET ;Return ;..... ; ; ; Ok, that's all of the modem dependant routines that BYE3 uses, so if ;Setup to write register 4 OUT SPORT MVI A,WRREG4 OUT SPORT MVI A,1 ;Setup to write register 1 OUT SPORT MVI A,WRREG1 OUT SPORT MVI A,5 ;Setup to write register 5 OUT SPORT MVI A,DTROFF ;Clear DTR causing hangup OUT SPORT PUSH B ;Save in case it's being used elsewhere MVI B,20 ;2 second delay ; OFFTI: CALL DELAY ;0.1 second delay DCR B JNZ OFFTI ;Keep looping until finished POP B ;Restore BC MVI A,3 ;Setup to write register 3 OUT SPORT MVI A,WRREG3 ;Initializset. ; MDOUTST:IN SPORT ANI TBMT ;Mask it RET ;Return ;..... ; ; ; The following is a routine that will output one character in register ; A to the modem. REMEMBER, that is register A, not register C. ; ; **** Use MDOUTST first to see if buffer is empty **** ; MDOUTP: OUT DPORT ;Send it RET ;Return ;..... ; ; ; These next routines set the proper baud rates for the modem. If you ; do not support the particular rate, then simply put the label in front ; of the SETINV routine. I   ; you patch this file into your copy of BYE3, then it should work out ; well. ; ;*********************************************************************** ; ; ENDOBJ: EQU $ ; IF RKEYS CHAT: DB 'CHAT',0 CHEK DB 'CHEK ',0 DIR: DB 'DIR',CR,0 DIR2: DB 'DIR *.* $',0 FILE: DB 'FILE ',0 GBYE: DB 'BYE',0 LDIR: DB 'LDIR ',0 LTYPE: DB 'LTYPE ',0 NEW: DB 'WHATSNEW',0 RBBS: DB 'RBBS',0 TYPE: DB 'TYPE ',0 XMDM: DB 'XMODEM ',0 ENDIF ;RKEYS ; ;------------------------------------------------DB '++ Cannot find .COM file ++',7,'$' CFLMSG: DB CR,LF,'[ COM file loaded ]',CR,LF,'$' ENDIF ;COMFILE OR EXFILE ; IF WELFILE WELFILN:DB 0,'WELCOME ' ;welcome file name, must be 11 chars. DB 0 ENDIF ; IF COMFILE COMFCB: DB 0,'RBBS COM' ;.COM file name, must be 11 chars. DS 21 ;rest of .COM FCB ENDIF ;COMFILE ; IF EXFILE EXITFCB:DB 1,' COM' ;exit filename, must be 11 chars. DS 21 ;rest of exit fcb ENDIF ;EXFILE ; ; ; These areas are not initialized ;ssword, CR-only to erase it ; ; ; (Allow room for larger password to be entered) ; DB 0,0,0 ; PWMSG: DB CR,LF,'Enter Password: ',0 WRGMSG: DB 'Incorrect password',CR,LF,0 ENDIF ;PWRQD ; IF BOOTMSG PLSMSG: DB CR,LF DB 'Please Wait... ' ;boot message goes here DB CR,LF,0 ENDIF ;BOOTMSG ; IF COMFILE LSMSG: DB 'Loading system...',CR,LF,0 ENDIF ;COMFILE ; IDMSG: DB '++ Invalid drive, returning to A: ++',0 ; IF CPM2 IUMSG: DB '++ Invalid user number, returning to 0 ++'19*### %͉"}!h"5!+#{zڑcC_R3#3w #{#z3+~#~3+~w#~w3|/g}/o#**}"#s#r#!"*12:&.6>!ͼ :5͡ :6 PBYE*"l29G h!]~/V#~2 AʃRVQV!ͿͿ1w 2_> 2 >2$9ƒpj1>2<JJEh9ʑ\´>2<9ʑe>2<9ʑe>2<9ʑe>2<9ʑe>2<9ʑÆ----------------------- ; ; Program version number message. ; VMSG: DB CR,LF,'<<<< BYE3 >>>> Micro Cornucopia Magazine',CR,LF,'$' ; NULMSG: DB CR,LF,'Nulls, if needed, (0-9)? ',0 ; CRMSG: DB CR,LF,CR,LF,0 ; IF PRNTGB GBMSG: DB CR,LF,' Good-bye, call again...' DB CR,LF,CR,LF,0 ENDIF ;PRNTGB ; RS1MSG: DB CR,LF,'Type "R" to resume, anything else to ' DB 'warm boot: $' ; RS2MSG: DB 1AH,'Resuming...',CR,LF,'$' ; IF USRLOG AND PWRQD ATMSG: DB CR,LF,'Number of logon attempts: $'  PEND: EQU $ ;The following area is not initialized ; IF COMFILE OR EXFILE CURRFCB:DS 2 ENDIF ;COMFILE OR EXFILE ; OPTION: DS 1 TOCNTM: DS 1 TOCNT: DS 2 ; ; ; Save the CP/M jump table here ; VCOLDBT: DS 3 VWARMBT: DS 3 VCONSTAT:DS 3 VCONIN: DS 3 VCONOUT: DS 3 VLISTOUT:DS 3 VPUNCH: DS 3 VREADER: DS 3 ; ; ; Since these areas are not initialized, the following counters will not ; be changed by subsequent loads of this program ; IF USRLOG OLDUSR: DS 2 NEWUSR: DS 2 NONUSR,0 ENDIF ;CPM2 ; CLMSG: DB CR,LF,'[Carrier Lost]',CR,LF,0 ; IF TIMEOUT ITOMSG: DB '[Input timed out]',7,0 ENDIF ;TIMEOUT ; IF FKEYS MFSMSG: DB 'Message from Sysop:',0 SGDMSG: DB 'System is going down....' DB 'please use BYE to log-off, thank you',0 ENDIF ;FKEYS ; LFMSG: DB CR,LF,CR,LF,0 ; IF PRNTWB WBMSG: DB CR,LF,'Booting CP/M... ',CR,LF DB 0 ENDIF ;PRNTWB ; IF COMFILE OR EXFILE PTSMSG: DB '++ Program area too small! ++',7,'$' CNFMSG: DB CR,LF !"7  h !8 p  /2 TʚRHrP  %>2>>2?>2=~<'w#~<'wv+~G̀xƐ'@'_>22?>2=2=2>2>2!XO͵y0ڰ:Ұ02!! \  \<*2|!2*O͵IXIX!7 e!-X 9mZ9m2Ϳ9xm=7GZ:=2=:2?:!ژ:2!A:!ڼʼ:2!fcQ x( ** " !s! *+++ENDIF ;USRLOG AND PWRQD ; IF USRLOG SUMSG: DB CR,LF,'Number of logons: $' ENDIF ;USRLOG ; IF USRLOG AND CALLBAK VCMSG: DB CR,LF,'Number of voice calls: $' ENDIF ;USRLOG AND CALLBAK ; IF LGONMSG LOGMSG: DB 'Baudrate determined by your input (300/1200 bps)',CR,LF DB 'Send several C/R''s to set baudrate....',CR,LF,0 ENDIF ;LGOMSG ; ; ; Access password (ends in carriage return) - keep password here ; IF PWRQD PASSWD: DB 'MICRO C' ;the password itself DB CR ;end of pa: DS 2 ENDIF ;USRLOG ; IF RKEYS BYTEA: DW 0 BYTEB: DB 0 ENDIF ;RKEYS ; DS 60 STACK: EQU $ ;local stack OBJEND: EQU $ ;..... ; ; END   ~#:Q>21w !1w 2V|F\>!~#j Bj:2 !" : I˜* +" |i: =^!AJX:>> j: OyTP :G͵ :A N͵#~# & @7"!> !> :>J2> ) jO, !"IXõWAT Z AT Q1 E0 M0 S2=128 S0=2 ͱͿ³A AT Z ͱͱO~#~>>>D>>>>remote user) and inaccessable (if you limit MAXUSR in BYE.COM to less than 15). Yet the remote user may run these programs no matter where on the system they are logged. If you are interested in the source code and more documentation on ZCPR, get Kaypro Disk #22. This disk provides a version of ZCPR for the older Kaypro 2's and 4's and versions for the Kaypro 10 and the new 4/84 and 2/84. The new Kaypro 4's and 2's (2/84's & 4/84's) can be identified by their non-glare screens and 63K CP/M cold bostem is not the original size shipped with your Kaypro. The other improvement is that you may use a semi colon as well as a colon to log on to a drive. In other words, A; has the same effect as A:. This will only be true when you are comunicating with the CCP ( actually the ZCPR ) or in other words when the A> prompt or B> is on your screen and you are entering commands to CP/M. The semi colon WILL NOT work with PIP. If you don't want to use this feature there are hex files that do not implement Ϳ>>>>Wͅ>>W>>a>a <<<< BYE3 >>>> Micro Cornucopia Magazine $ Nulls, if needed, (0-9)? Good-bye, call again... Type "R" to resume, anything else to warm boot: $Resuming... $ Number of logons: $ Please Wait... ++ Invalid drive, returning to A: ++++ Invalid user number, returning to 0 ++ [Carrier Lost] [Input timed out]Message from Sysop:System is going down....please use BYE to log-off, thaot sign-on. The older 4's still have a 64K system and owners of these machines should follow the directions for the Kaypro 2 in the paragraphs that follow. Enhancements:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: This version of ZCPR differs from the version on disk #9 in a couple of ways. Mainly it fixes the bugs in the way the old version handled control charac- ters. The most common complaint on the old ZCPR was that you could not pass control character strings through to t BYE--ZCPR For Protecting Remote Systems This version of ZCPR has been assembled to ignore the commands that a remote user could use to destroy your RCP/M. The commands ERA, SAVE, REN, and JUMP are ignored by the CCP so that dangerous commands or programs cannot be created or executed. Also this version uses USER AREA 15 as the default area to search for a .COM file not present in the currently logged area. This makes it possible to keep .COM files such as XMODEM and BYE in an invisible (to the it. ( Described later ) THE FILES ON THIS DISK **************************************************** *.HEX Assembled ZCPR files each one set up for a specific computer including................. 2ZCPR.HEX ZCPR for the Kaypro 2 w/semicolon option 484ZCPR.HEX ZCPR for the Kaypro 4 w/semicolon option 10ZCPR.HEX ZCPR for the Kaypro 10 w/semicolon option *.SUB Installation SUBMIT files each one set up for a specific computer including................. 2INSTALL.Snk you WELCOME he console (or the printer with a ^P). This version fixes that. The installation procedure has also been changed to use SYSGEN rather than MOVCPM. The problem with MOVCPM is that many people got the BIOS update from Kaypro but did not incorporate it into their MOVCPM. The result was erratic keypad operation. The problem with SYSGEN is that some people don't know what they have on their system tracks. Ah well, can't win them all. If you do the installation and then can't boot chances are that your sy  UB Installation commands for Kaypro 2 4INSTALL.SUB Installation commands for Kaypro 4 running CP/M version F and lower. GINSTALL.SUB Installation commands for Kaypro 4 running CP/M version G. 10INSTAL.SUB Installation commands for Kaypro 10 version F. 10GINSTL.SUB Installation commands for Kaypro 10 version G. EX14.COM A fantastic replacement for SUBMIT.COM. Used to install ZCPR with the above files. Don't forget old 4's use the Kaypro 2 files. Kaypro 4 files are f running version G use 10GINSTL.SUB. 2. You should be able to boot your 10 from a floppy. In case there is a problem putting ZCPR on the system tracks, you will be able to recover by booting from a floppy and running PUTSYS.COM to restore the system tracks to the hard disk. Create a floppy disk that you can boot from by using GENFLPY.COM. To use GENFLPY enter GENFLPY . It will ask for a source drive. Respond to this question with a carriage return and answer Cays that ZCPR is installed. From now on ZCPR will be trans- ferred to any disk you sysgen from this disk. New Kaypro 4's and 2's Version F and earlier :::::::::::::::::::::::::::::: Follow the directions for the Kaypro 2 and old 4 except substitute 484ZCPR.HEX for 2ZCPR.HEX and 4INSTALL.SUB for 2INSTALL.SUB. New Kaypro 4's and 2's Version G ::::::::::::::::::::::::::::::::::::::::::: Follow the directions for the Version F and earlier except substitute GINSTALL.SUB for 4INSTALL.SUB. (You R.HEX The following files should already be there (if you didn't erase or move them): DDT.COM PUTSYS.COM Enter: EX14 10INSTAL for version F or EX14 10GINSTL for version G The program will display the version number of your PUTSYS.COM. Version F of CP/M has a PUTSYS version of 1.4. Version G has a PUTSYS version of 1.4G. You will be able to abort the operation at this point if the version of your PUTSYS is not correct. You will be prompted to enteror the new Kaypro 4's and 2's with a 63K signon message. In addition there are two versions of the 63K CP/M. Versions F and earlier use the standard 4INSTALL.SUB. Kaypro's running version G need to use GINSTALL.SUB. To find out what version you have hit the reset button and boot CP/M. The version letter will follow the "2.2" in the signon message. If you have a 64K CP/M there will be no version letter. Follow the directions for the Kaypro 2 for 64K CP/M. INSTALLATION ************************** for the destination drive. Now make sure you can boot the 10 from a floppy by having the floppy in the disk drive and hitting the reset button. The floppy drive becomes drive A: and the hard disk becomes drives B, and C. If you are successful with this also practice reinstalling your system tracks by running PUTSYS. If you can boot from the floppy and restore your system tracks you are ready to continue. But first put a copy of PUTSYS.COM on the floppy as well (just in case). will still use 484ZCPR.HEX). Kaypro 10 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Since ZCPR lives on your system tracks and your system tracks live on the hard disk be very careful when installing ZCPR on your 10. Please observe the following precautions. 1. Your Kaypro 10 must be running CP/M version F or G. This is not the monitor version but the BIOS version and is displayed in the cold boot sign-on. If you are running version F, use 10INSTAL.SUB. If you are  a carriage return to continue or control C to abort. If you continue.............. You will notice some activity then the phrase and then the A0> prompt. Examine the directory and you should see a file called ZPUTSYS.COM This file will do the same thing as PUTSYS.COM (namely write system tracks to your hard disk) but will write ZCPR instead of the CCP when run. To complete the ZCPR installation enter: ZPUTSYS When the A0> prompt returns hit the reset butt************************************ Kaypro 2..... and old 4's:::::::::::::::::::::::::::::::::::::::::::::::::: Format and sysgen a disk from your CP/M master and pip the following files onto this disk: From your CP/M system disk: SYSGEN.COM DDT.COM From this disk: 2ZCPR.HEX EX14.COM 2INSTALL.SUB Boot the disk you created in A: and enter EX14 2INSTALL The disk drives will jump to life and after a bit of grinding you will get a message that s 3. Verify that you have a good copy of the files on this disk by entering CRC . This program will do a cyclic redundancy check on all the files and display *MATCH* for all the good files. If you do not get a match on all the files, return the disk for a new copy and do not install ZCPR with this disk. To begin the procedure, pip the following files onto your A: drive user 0 from this disk: EX14.COM 10INSTAL.SUB for version F or 10GINSTL.SUB for version G 10ZCP  on on the back of your computer to make sure it will still boot from the hard disk and enjoy ZCPR. If it will not boot, boot from the floppy and run PUTSYS to restore your original system tracks to the hard disk. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: *#"ɯ2i2}! "!"]]2 s : ~# ++FILE NOT FOUND++$: F*}’">͇†]<  CANNOT CLOSE CRCFILE$CRCKLISTCRCSK FULL: CRCFILE$  w# !]͐ DONE$!e S!]Q !eZ @ --> FILE: XXXXXXXX.XXX CRC = oS) \<‘@ ++OPEN FAILED++ !" !" * | ʹ) \!~2 #" Ý: ) > T : ) @ ++FILE READ Eth file - ! ~T #M M 2 2 2 2 ! >2 3o: : @ ***No CRC Files found***$> ʉ ʉw#: <2 P6: .6@ Can not parse string ! ~ʽT #ñM ! > 6 #6^#6! ~T #! 4M #x] #e w~ T #>2 @ - s M@ File not found ! 4 >2 o: G: „: G: „@ *Match* 2 ! 4@ <-- is, was --> : ) > T : ) M 2 ! 4<2 ~# @ Not a space between CRC values<2 G-CATALOG??? Using CRC Type CRC to verify all the files on this disk. Type CRC *.* F to generate CRC's for an entire disk and create a CRC file (CRCKLIST.CRC) for checking the CRC's of a copy of the disk etc. Omitting the F will suppress creation of a CRCKLIST.CRC file. *.* can be replaced with an unambiguous file name for checking just one file. RROR++ <* |): o% |g}o" 2  ; 0T ~T #~A > T > _h : F{͇2h2|: ʲ !\   :\2 ! \  \ ! \  \! \  \<7=Ɓo&   ]  2h2|2   ~$#~# x  : F} *}= ">͇1 ].”#””͡”››tK››͸›* =: =͔="  ʳ ª~#.  ¿~  #~  .+~#0:0~#!A.O.Gy~#0M0 K MMɷ:m2 FSÄCRCKLIST$$$››tK›, › **}|!"*{z*~]*"Ü  DISK FULL: CRCFILE$!"*~#CRC.COM 5.0 6/18/82CRCKFILE???!9" 1 M @ CRC Ver 5.0 CTL-S pauses, CTL-C aborts :] O@ ++Searching for CRCKLIST file++@ Now searching for "CRCKFILE" file++ !  1 .) F!  ͡]͸! ͔0CRCKLIST???CRCKFILE???!9" M à*,*.}|ډ!".*,{z{** u*.".G*.",!".***,}>*.#".ɯ22)! ",". <  NO FILECRC FILE$!   >. @ Checking wi match - : ̓ : J M @ Quantity of lines failed parse test - : ̓ : ~ M @ Quantity of file(s) not found - : ̓ * d͔  ͔ 0T  Җ Wyʩ 0T 0ztiil   --> FILE: BYE .ASM CRC = 69 78 --> FILE: BYE .COM CRC = E9 84 --> FILE: 2ZCPR .HEX CRC = 87 76 --> FILE: 484ZCPR .HEX CRC = 09 22 --> FILE: 10ZCPR .HEX CRC = 89 1E --> FILE: XMODEM .ASM CRC = 7B B5 --> FILE: EX14 .COM CRC = 02 E3 --> FILE: EX14 .DOC CRC = 9B 8F --> FILE: INTTERM .COM CRC = D1 3F --> FILE: XLATETBL.ASM CRC = 9B DB --> FILE: XMODEM .COM CRC = 2E E0 --> FILE: INTTERM .MAC CRC = 82 4A --> FILE: 10INSTAL.SUB CRC = 20 64 --> FILE: -23-Dy arguments - $EX 1.4 11-22-82$ $ppppppppppppppppppppppppppppppppI"""~+"21*|g."*" *! 1*~*"*"#^#V!_:O*AâÐu!9"!ͥ͢ʽ½ͥ*#w">*:2́a OC[[ 2> O:y½ͨÚ*"222Úͥ͢ʽ 7ͨOù>ù>ù>ù> > 2)u!A0> 2*h> ~!)w¹O:(yʹ:&yʹ#!):8=28ʏ jw:8ʉ> > ~> ~>ù>!(£w>ù>2)!&u2&2'ù>2)!'u2'2&ù*6}|ʉw+*###>E#>X#>Oͤ*$:6+6} %. 6+6X+6E+:w+:w+6*'ͤͤͤͤ*,ͪ fͤ ͤͤ zͤ|`ڣ{G @;:?$.#<>G@G$^|1Y:Y12+!U _^#V{  EX 1.4 - 11/20/82 Thanks to Joe Cutler, Stan Hanson, and Ron Fowler for EX.* and the information used to create this version. This file and the source for EX14 are based upon the previous EX*.* files. EX 1.4 is a maintenance update to EX 1.2 and EX 1.3 (never released). Problem: BASCOM would not execute under EX. Reason: BASCOM is doing system integrity checks using the BDOS+1 address. EX was not preserving the required information so that BASCOM would execute. ISK.DOC CRC = D6 38 --> FILE: GINSTALL.SUB CRC = 93 CA --> FILE: BYEZCPR .DOC CRC = 7A 1D --> FILE: CRC .COM CRC = B2 07 --> FILE: CRC .DOC CRC = E5 81 --> FILE: 10GINSTL.SUB CRC = F5 EA --> FILE: 4INSTALL.SUB CRC = C6 8E --> FILE: 2INSTALL.SUB CRC = 43 5C --> FILE: XMODEM .DOC CRC = 07 EDu u!Kw!Ww2*"x: :y2è*~+"*#"**{z­og"!m*å1!J!m*! (~#:!0:A[a{2:~$#Oͨ!A!!u >>>Ex Aborted<<< $ (Ex Active)$ (Ex Completed) >$ßâåèBDOS>   "IH! !B"$$HB!$BD$$$$H"D $$I """~+"21*|w+#~!A:+P_^#V{P w#&*2#"2!)6!86kb"0"9 :(:&:8<28", ʜ os#r#:*b ʜ ‰o>  ~ µ> #_ê!ͤ@ͤ*2*0~# 6 ~#_   |{0_~#'_x{ w#0SUB error line # $ (Ex Already Present)$ Text buffer empty$ Input/EX Buffer Overlap$ No parameter or default parameter$ Parameter$ File filename.typ$ not there$ Control character$ Too man Resolution: See next problem resolution. Problem: Unpredictable results when executing MBASIC under EX. Reason: MBASIC (and others) were not subtracting 6 from the BDOS+1 address when determining available memory. Resolution: EX now refreshes the storage in the 6 bytes below the BDOS+1 address during any warmboot request. The enhancements added with EX 1.2 are: ^: EX runtime re-execution function ^? EX runtime wait for carriage return `Xsub Already Presen!9"$1>2ͤ*?*}_|W!x< ~#/bkxp :/<2/Z~#2.:.2.lA+";#:o&6 !S0> 2*h:!"2>2!"4*2#"2:  G*4H'6 #6 #"4òe!='2|\<%!]&6.#e&6$z*4!"4\%*46"6}|q2&2'2(28!"2*;"9"= „2u| > 2O:&yʯ;A^$2) O:8yuNu͒:; ?|$%.ʘ#ʓ<ʪ>  t' logic Input/EX buffer overlap detection EX runtime recursion prevention (Ex Already Present) EX runtime prompt mode character logic The enhancements added with EX 1.1 are: ;; EX only comment support ^. Print suppression toggle ^<..^> Immediate print function ^# EX message suppression toggle ^| Carriage return/line feed function ^$ Default parameters' support Logic to prevent ZCPR re-entrance to EX.COM (EX.COM is not reentrant) --Larry Scuted as if was entered from the console. EX14.COM may be terminated during execution by entering control-C from the console. EX14.COM submit file conventions are: [note: unless otherwise stated, the `<.......>' sequences are used only to indicate character strings that must be replaced with the values described.] ^ generates the corresponding control character. Lowercase letters a thru z are converable on CP/MIG XA1 ACCESS database] The files used to test EX14.COM are: EX14.COM EX14.TST (must be renamed to .SUB before executing test) XSUB.COM The files used to execute EX14.COM are: EX14.COM SUB.COM (used to generate simple *.SUB files) [note: Any good CP/M editor may be used to create *.SUB files] (cr is carriage return) EX14.COM may be invoked two ways: 1. EX14 cr This form will cause EX to prompt with a line number an ^ control support, $<1 thru 9> parameter substitution, and $ escape support continues during this display mode. (Example: ^<^[ETest EX 1.4^|^> will generate the sequence to clear the screen on the H/Z19 terminal and display `Test EX 1.4' at the upper-lefthand corner of the screen and the cursor will be on the next line.) ^: causes EX to re-execute the .SUB file from the beginning. ^? causes EX to wait for a carriage return response from thteeger [70315,1120] on CompuServe [note: The changes from file EXFIX.DOC have been incorporated into EX12.*] EX is a nifty and fast way of executing .SUB files, (uses ram as the SUB file buffer rather than spreading it out on disk). EX also allows batch entry of a series of commands which it stores in memory for subsequent continuous execution. EX relocates itself and its buffer to high memory just below CCP and adjusts the CP/M BDOS entry to protect itself. -ted to uppercase. $<1 thru 9> generates parameter <1 thru 9> substitution the same as SUBMIT, unless `^$' is being used as described below. ^$ will generate a list of parameters that will be used in the $<1 thru 9> parameter substitution if the user does not provide any parameters or only some of the parameters on the EX command line. ;; generates an EX only comment (the ;; and the remainder of the cd `:' for each command line to be executed. A carriage return entered by itself terminates the prompting and starts execution of the command lines that have been entered. 2. EX14 cr This form will cause EX to load the into memory and perform substitution the same as SUBMIT, with the addition of the `^$' support for missing parameters. After all parameters have been substituted the text from the file is exee console. Control-C will terminate EX at this point also. $$ generates the $ (dollar-sign). $^ generates the ^ (caret or up-arrow). $| generates the | (broken vertical bar). EX14.COM(.BIN or .OBJ) was generated from EX14.ASM using EX14.SUB and the files mentioned above. --Larry Steeger 11/20/82 BIN or .OBJ) was generated from EX14.ASM using-Stan Hanson 05/24/82 EX replaces the functions of both SUBMIT.COM and XSUB.COM from Digital Research, Inc. --Larry Steeger 08/06/82 The files used to assemble EX14.ASM using EX14.SUB are: ED.COM EX14.ASM EX14.SUB MAC.COM RELS.UTL (or REL.UTL see note in EX14.SUB) SID.COM SUBMIT.COM and XSUB.COM (or a previous version of EX.COM may be used) [note: REL.UTL is available on CP/MUG Volume #38] [note: RELS.UTL is availurrent line are not moved to the EX command buffer.). | generates a Carriage Return. ^| generates a Carriage Return and Line Feed. |,cr,lf,1AH(EOF) will eliminate all characters from the last | thru this sequence. ^. toggles print suppression for characters from SUBMIT file. (Example: DIR ^.*.COM^. will execute DIR *.COM but only DIR will be echoed to the console.) ^< forces immediate display of the characters following it until ^> is encountered.  sysgen a | | save 40 cpmgg.com ddt cpmgg.com i484zcpr.hex r2980 a2090 JMP F722 . ^C sysgen | a | | ^C ^<******** ZCPR +++++++++++++++++++++++> Installed ***********^> era cpmgg.com ò  0123456789-, .!͠{!͠{_v͆͘-dd;....modem status interrupt .... $....keyboard status int1ÕD INT version 1.2 (1984 04 05) wait until your discs deselect, then press any key to start press RESET to exit the program $!!   !!!|G^ìerrupt .... $ h $ $0123456789abcdef!_O ~2V!_O ~2U U\ M1 o>oͨ>ñ>(ñ!tXʱñ!Xʱñ o>oͨ>ñ!͠ {ñ>(ñV^zݾ {ݾ >rsV^ wzݾ {ݾ rs~ ~ >V^rsV^ ~zݾ {ݾ rs_!t͠{:@>2@!{X!AA2@RE(!T~_#  ;*********************************************************************** ;* INT - Interrupt driven terminal handler for KAYPRO's * ;* * ;* Copyright (c) 1984 by Robert Philip * ;* All Rights Reserved * ;* * ;* This program was written to ease the use of Kaypro computers as * ;* computer terminals running at HIGH (>1200 baud) speed. It is * ;* freely released to the public for non-commercial purposes. Please * ;* give this pro wr2 equ 2 wr3 equ 3 wr4 equ 4 wr5 equ 5 wr6 equ 6 wr7 equ 7 rr1 equ 1 cr equ 0dh ;ascii carriage return lf equ 0ah ;ascii linefeed stack equ progend+1000h intorg equ 08000h ;My kaypro 10 manual says this is above ;the rom-bios memory (the alternate bank) intcode equ 8900H ; where interrupt drivers begin qsmdmin equ 2048 ;2Kb input queue allows 19.2Kbaud input to the ;screen... qsmdmout equ 100 ;not too likely to overrun this from the keyboard qskbdin equ 100 ;this one eitherte source to take advantage of phase and dephase ** ;** capabilities of M80 reducing .COM file size from 36K to ** ;** approx 5K...................................4/5/84 DmC ** ;** ** ;** 3. Added keypad and cursor control key translation ** ;** ( One key generates up to 16 characters)....5/23/84 DmC ** ;** ** ;*******************************************************************:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; all the initialization stuff is org'ed to 0100h ; so that later incarnations can initialize and then re-use ; the initialization memory. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: start: ld sp,stack jp start1 ;branch around this data stuff.... ; program up 'the chip'. ; this good stuff is for the modem 'modem' port siost: db 00011000b ;channel reset db wr4 ;write register 4 next gram to your friends. * ;* * ;* Thanks to Rick Parson, upon whose idea this program was built * ;* Commercial use is prohibited except by written release by * ;* Robert Philip. * ;* * ;* Robert Philip * ;* 106-1300 Richmond Road * ;* Ottawa, Ontario * ;* Canada * ;* K2B 8L2 * ;* * ;****************** ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; some macros for saving/restoring the registers. ; since these routines are intended to work even when later ; releases include disc file capture and other good stuff, ; I save everything. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: regsav macro push af ;save everything on the stack push bc ;since the KAYPRO uses the alternate push de ;registers for the rom-bios push hl push ix **** ;*********************************************************************** .z80 ; use Z80 instructions vers equ 1 subvers equ 2 year equ 84 month equ 4 day equ 5 bdos equ 5 pstring equ 9 conin equ 1 dcio equ 6 mdmctl equ 06h ; use modem rs232 port mdmport equ 04h kbdctl equ 07h ; the usual keyboard arrangement kbdport equ 05h TXreset equ 028h ;reset after error on sio modbusy equ 04h statreset equ 010h ;external/status reset wr0 equ 0 ; SIO write registers wr1 equ 1  db 01000100b ;16x clock, 1stop bit, no parity db wr3 ;write register 3 db 11000001b ;Rx 8bits/char, Rx enable db wr5 ;write register 5 db 11101010b ;DTR, Tx 8bits/char,Tx enable,RTS db wr1 ;write register 1 db 00010010b ;int on all Rx chars, Tx int enable db wr2 ;write register 2 db (intbase and 0ffh) ;base of interrupt vector sioend: ; ; now some programming for the keyboard ; we only want to recieve characters from it ; ksioint: db wr1 ;write register 1 db 00010100b ;in***************************************************** ;*********************************************************************** ;** Micro Cornucopia Fixes.................. ** ;** ** ;** 1. Fixed the console output to strip parity bit to get rid ** ;** of funny characters on our 4-84.............4/4/84 DmC ** ;** ** ;** 2. Rewro endm regres macro pop ix ;restore the registers saved with pop hl ;the above macro pop de pop bc pop af endm qins equ 0+1 ;disp to insertion pointer qrem equ qins+2 ;disp to removal pointer qsize equ qrem+2 ;disp to qsize qchrs equ qsize+2 ;disp to #chars in queue qdata equ qchrs+1 ;disp to qdata queue macro qn,qs qn: dw 0 ;insertion pointer dw 0 ;removal pointer dw qs ;queue size dw 0 ;number of characters in queue ds qs ;reserve space endm aseg org 0100h ;::  t on all Rx chars, first Rx, ;Tx int disable, external int disable db wr2 ;write register 2 db (intbase and 0ffh) ;base of interrupt vector ksioend: hello: db lf,'INT version ',vers+'0','.',subvers+'0',' ' db '(19',year/10+'0',year mod 10+'0',' ' db month/10+'0',month mod 10+'0',' ' db day/10+'0',day mod 10+'0',')',cr,lf,lf db 'wait until your discs deselect, then ' db 'press any key to start',cr,lf,lf db 'press RESET to exit the program',cr,lf,'$' start1: ; First move the qagain ld hl,hexbytes ;base addr of hex table and 0fh ;bottom nibble first ld b,0 ;add to the base of hex table ld c,a add hl,bc ld a,(hl) ;get the 'hex' character ld (hexmsg+1),a ;into the message buffer pop af ;get our character again rr a ;we want the left half this time rr a rr a rr a and 0fh ;make sure ld hl,hexbytes ld b,0 ld c,a add hl,bc ld a,(hl) ld (hexmsg),a ld c,pstring ;now print it out ld de,hexmsg call bdos regres ;restore regs ret ; pfor 'the next release') .phase intorg ; ; i/o queues for modem and keyboard ; queue inqmdm,qsmdmin ;modem input queue queue outqmdm,qsmdmout;modem output queue queue kbdq,qskbdin ;keyboard input queue intend: NOP ; move to an even page boundary ; .dephase NEXTSEG: NOP .phase intcode ; this is the 'interrupt vector table' intbase: dw outkbd ;keyboard output interrupt dw stkbd ;keyboard status interrupt dw inkbd ;input interrupt from keyboard dw inkbd ;input interrm input interrupt inmdm: regsav ;save regs in a,(mdmport) ;get character ld ix,inqmdm ;address of modem input queue call qinsert ;stuff character into queue or a ;if queue full, I should probably do jp z,common ;something, but instead, I just pitch pop af ;the overflow character jp common ;common exit path ; modem status interrupt stmdm: regsav ;save regs ld de,mstatmsg ld c,pstring call bdos in a,(mdmctl) ;get status call prhex ;print it ld a,rr1 out (mdmctl)'s into LD DE,INTORG ; high RAM LD HL,NEXTCODE+1 LD BC,INTEND-INTORG LDIR ld DE,intcode ; Now move the interrupt handlers LD HL,NEXTSEG+1 ; up to high memory LD BC,PROGEND-intcode LDIR ld de,hello ld c,pstring call bdos ld c,conin call bdos ;get a char(let discs de-select) ; program the modem port ld c,mdmctl ;the port ld b,sioend-siost ;how many bytes ld hl,siost ;from here otir ;stuff.............. ; now set the interrupt parameters for keyboard ldrint cr,lf on screen crlf: ld de,crlfmsg ld c,pstring call bdos ret ; common interrupt return common: regres ;restore registers ei ;just in case reti ;return from interrupt ; keyboard status interrupt stkbd: regsav ;save regs ld de,kstatmsg ld c,pstring call bdos in a,(kbdctl) ;get status call prhex ;print it ld a,rr1 out (kbdctl),a ;ask for rr1 in a,(kbdctl) call prhex ;print it call crlf ld a,statreset out (kbdctl),a ;reset status on modem upt from kbd (parity) dw outmdm ;modem output interrupt dw stmdm ;modem status interrupt dw inmdm ;modem input interrupt dw inmdm ;modem input interrupt (with parity?) mstatmsg: db '....modem status interrupt .... $' kstatmsg: db '....keyboard status interrupt .... $' hexmsg: db ' ',0,0,'h $' crlfmsg: db cr,lf,'$' hexbytes: db '0','1','2','3','4','5','6','7' db '8','9','a','b','c','d','e','f' ; ; print hex value passed in 'a' ; prhex: regsav ;save regs push af ;save accumulator ,a ;ask for rr1 in a,(mdmctl) call prhex ;print it call crlf ld a,statreset out (mdmctl),a ;reset status on modem jp common ;go to common return ; output interrupt on modem port outmdm: regsav ;save registers ld ix,outqmdm ;modem output queue call qget ;get a character into 'e' or a ;did we get one jr nz,omdm1 ;no..reset the output interrupt ld a,e ;character into 'a' out (mdmport),a ;there it goes... jp common ;split omdm1: ld a,TXreset out (mdmctl),a ;reset T c,kbdctl ;kbd port ld b,ksioend-ksioint ;this many ld hl,ksioint ;from here otir ;stuff it.... ; set up interrupt reg, interrupt mode ld hl,intbase ;address of interrupt vectors ld a,h ;only want the high byte ld i,a ;in the interrupt register im 2 ;the best.. ; now go sit in a loop looking for characters jp doit NEXTCODE: NOP ; org up high, so that we don't interrupt into the middle of ; the rom-bios while it is doing screen stuff (or other good ; things planned  jp common ;go to common return ; keyboard output interrupt outkbd: ld a,TXreset ;rarely do we output out (kbdctl),a ;to the keyboard..but sometimes.. jp common ; keyboard input interrupt inkbd: regsav ;save regs in a,(kbdport) ;get character ld ix,kbdq ;address of keyboard input queue call qinsert ;insert character into queue or a ;queue full? jp z,common ;no...just return pop af ;should probably care, but I don't, so just jp common ;bit-bucket the character ; mode  x int pending jp common ;and split ; queue insertion routine ; assume regs were saved before call ; IX points to first byte of queue structure ; if the queue is full, return with 0ffh in 'a' ; otherwise stuff the character and increment the ; insertion pointer. qinsert: di ;no ints while playing with q's push af ;save character ld d,(ix+qchrs) ;is q full? ld e,(ix+(qchrs-1)) ld a,d cp (ix+qsize) jr nz,qok ;nope ld a,e cp (ix+(qsize-1)) jr nz,qok ;no...insert char ******************************************************************* ;** The keyboard translation takes place here. When a keyboard character ** ;** is picked out of the keyboard queue, it is checked to see if it ** ;** is a vector or data pad key. If not the character is passed into ** ;** the output queue. If it is from the special keys it is translated** ;** and as many bytes as need to be sent are dumped into the output ** ;** queue. ** ;************************************************or a jr nz,qgetch ld a,0ffh ;yep...return a 0ffh in 'a' ei ;ok....hit a key ret qgetch: ld d,(ix+qchrs) ;number of chars in the queue ld e,(ix+(qchrs-1)) dec de ;we are removing one ld (ix+qchrs),d ld (ix+(qchrs-1)),e ld d,(ix+qrem) ld e,(ix+(qrem-1)) ;get removal pointer ld bc,qdata ;displacement to data push ix pop hl add hl,bc ;point to data add hl,de ;to the char to remove ld a,(hl) ;get char push af ;save it for later inc de ;increment remove per key fstent: ld hl,mapout loopp: add hl,de djnz loopp trnloop: ld a,(hl) ; get byte of translation string or a ; is it 0? ret z ; return if so ld e,a ; oqqqq wants character in e push hl call oqqqq ; stuff in output queue pop hl inc hl ; bump pointer jr trnloop ; get next byte of string tranflag: db 0ffh ;************************************************************************** ;** The mapin and mapout tables ** ;*** ld a,0ffh ;yes..let the caller take care of it ei ;af is on the stack ret qok: inc de ;one more char in queue ld (ix+qchrs),d ld (ix+(qchrs-1)),e ld d,(ix+qins) ;get insertion pointer ld e,(ix+(qins-1)) ld bc,qdata ;displacement to data pop af ;get char back push ix ;save it pop hl ;move into hl add hl,bc ;hl points at beginning of data area add hl,de ;plus insertion pointer ld (hl),a ;insert in queue inc de ;increment insertion pointer ld a,d ;if > size of************************** ld a,e ;get character push hl push bc push de call kbdmap pop de pop bc pop hl ld a,(tranflag) ; see if translation just done or a ld a,0ffh ; fix translation flag for next time ld (tranflag),a ret z ; if translation done get out now oqqqq: ld ix,outqmdm ;output queue ld a,e call qinsert ;stuff character ;** If a character makes it into the queue af is popped off stack by qok ** ;** If not stack needs to be purged of the af leftal ptr ld a,d cp (ix+qsize) ;if > qsize then back to 0 jr nz,okinc2 ld a,e cp (ix+(qsize-1)) jr nz,okinc2 ld de,0 okinc2: ld (ix+qrem),d ;save it in structure ld (ix+(qrem-1)),e pop af ;get char back ld e,a ;into the right reg xor a ;zero 'a' ei ;any time now ret ; now, the queue processors ; first, the keyboard prinkbd: ld ix,kbdq ;address of the keyboard queue call qget ;get a character if there is one or a ret nz ;no characters.... ;****************************************************************************** mapin: db 0f1h,0f2h,0f3h,0f4h ;up, down left right db 0b1h,0c0h,0c1h,0c2h ;0,1,2,3 db 0d0h,0d1h,0d2h,0e1h ;4,5,6,7 db 0e2h,0e3h,0e4h,0d3h ;8,9, '-' ',' db 0c3h,0b2h ; enter, '.' db 0ffh ;************************************************************************** ;**** The Translated Values. 0 is the string delimiter which must be *** ;**** the last character in the string. There are 17 bytes for each *** ;****  the queue, cp (ix+qsize) ;then back to the start jr nz,okinc ld a,e cp (ix+(qsize-1)) jr nz,okinc ld de,0 okinc: ld (ix+qins),d ;save insertion pointer ld (ix+(qins-1)),e xor a ;success!!! ei ret ; queue removal routine.....return the character in ; e, 0ff in 'a' if error, 0 in 'a' if ok ; IX points to beginning of queue structure qget: di ;no ints while i play with q's ld a,(ix+(qchrs-1)) ;is size zero? or a jr nz,qgetch ;nope...remove a char ld a,(ix+qchrs)  there by qinsert ** or a ;stuffed? ret z ;yep pop af ;nope ret ;and return kbdmap: ld hl,mapin ld bc,mapout-mapin cpir ret nz ; return if not a special key trnslt: ; translate special keys ld de,mapin xor a ld (tranflag),a sbc hl,de ; this forms index to translate table ld de,0000 ld b,l ; keep it in b dec b ; for true index (hl inc'ed first on ; cpir jr z,fstent ; kludge to get at first entry ld de,17 ; number of entries possibl   special key so you can output up to 16 bytes ( to leave the *** ;**** last byte a 0 ). *** ;************************************************************************** mapout: db 0bh,0,0,0,0,0,0,0 ; up arrow db 0,0,0,0,0,0,0,0,0 db 0ah,0,0,0,0,0,0,0 ; down arrow db 0,0,0,0,0,0,0,0,0 db 08h,0,0,0,0,0,0,0 ; left arrow db 0,0,0,0,0,0,0,0,0 db 0ch,0,0,0,0,0,0,0 ; right arrow db 0,0,0,0,0,0,0,0,0 db '0',0,0,0,0,0,0,0 ; 0 on datapa *** ;************************************************************************** proutmdm: in a,(mdmctl) ;check if it's busy or not and modbusy ret z ;busy....back later ld ix,outqmdm call qget ;get a character or a ret nz ;there are none ld a,e out (mdmport),a ;send it ret ; modem input queue...get a char and use bdos to ; print it on the screen prinmdm: ld ix,inqmdm ;input queue call qget ;get a character or a ret nz ld c,dcio ;no 'cpm' processin;************************************************************************** ;*** Key Translation Table Overlay For INTTERM.COM *** ;*** Micro Cornucopia Magazine *** ;*** PO Box 223 Bend, Oregon 97709 *** ;*** *** ;*** Each key below can be translated into as many as 16 characters *** ;*** The termination byte and unused characters must be 0's *** d db 0,0,0,0,0,0,0,0,0 db '1',0,0,0,0,0,0,0 ; 1 on datapad db 0,0,0,0,0,0,0,0,0 db '2',0,0,0,0,0,0,0 ; 2 on data pad db 0,0,0,0,0,0,0,0,0 db '3',0,0,0,0,0,0,0 ; 3 on data pad db 0,0,0,0,0,0,0,0,0 db '4',0,0,0,0,0,0,0 ; 4 on data pad db 0,0,0,0,0,0,0,0,0 db '5',0,0,0,0,0,0,0 ; 5 on data pad db 0,0,0,0,0,0,0,0,0 db '6',0,0,0,0,0,0,0 ; 6 on data pad db 0,0,0,0,0,0,0,0,0 db '7',0,0,0,0,0,0,0 ; 7 on data pad db 0,0,0,0,0,0,0,0,0 db '8',0,0,0,0,0,0,0 ; 8 on dataThe files named .CPM are actually .COM files for CP/M. If you copy the files to a CP/M system without using 22DISK, just rename all *.CPM to .COM g ld a,e and 7fh ld e,a call bdos ;print the char that's in 'e' jr prinmdm ;get all chars input so far doit: ei ;in case they aren't halt ;wait til sumthin happens call prinkbd ;input from the keyboard call prinmdm ;process input from the modem call proutmdm ;process output to the modem jr doit ;skip back for the next int progend: end start  ;*** You must have 17 bytes for each key (either characters or 0's) *** ;*** including the termination byte. *** ;*** *** ;*** This file is assembled with ASM.COM as follows: *** ;*** ASM XLATETBL *** ;*** And overlayed on INTTERM.COM as follows: *** ;*** DDT INTTERM.COM *** ;*** iXLATETBL.HEX *** ;***  pad db 0,0,0,0,0,0,0,0,0 db '9',0,0,0,0,0,0,0 ; 9 on data pad db 0,0,0,0,0,0,0,0,0 db '-',0,0,0,0,0,0,0 ; '-' on data pad db 0,0,0,0,0,0,0,0,0 db ',',0,0,0,0,0,0,0 ; ',' on data pad db 0,0,0,0,0,0,0,0,0 db 0dh,0,0,0,0,0,0,0 ; ENTER on data pad db 0,0,0,0,0,0,0,0,0 db '.',0,0,0,0,0,0,0 ; '.' on data pad db 0,0,0,0,0,0,0,0,0 mapend: ;************************************************************************** ;*** now the output queue   r *** ;*** Then exit DDT with a ^C and save the newly patched .COM file: *** ;*** SAVE 16 INTTERM1.COM *** ;*** *** ;(((((((((((((((((((((((((((((((( DmC ))))))))))))))))))))))))))))))))))))) ;************************************************************************** mapout equ 0D0Ch ; mapout table location ; in INTTERM.COM file org mapout db slate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '7',0,0,0,0,0,0,0 ; 7 keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '8',0,0,0,0,0,0,0 ; 8 keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '9',0,0,0,0,0,0,0 ; 9 keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '-',0,0,0,0,0,0,0 ; - keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db ',',0,0,0,0,0,0,0 ; , keypad key translate db 0,0,0,OD true for Kaypro *** ;*** operation even if for a DC Hayes (it is still external ) *** ;************************************************************************** PMMI EQU FALSE ;TRUE, IS PMMI *** DCH EQU FALSE ;TRUE, IS D.C. HAYES *** H8 EQU FALSE ;TRUE, IS H8/H89 W/INS8250 MODEM CHIP *** EXTMOD EQU TRUE ;TRUE, IS NONE OF THE ABOVE! *** ;**********************************************************0bh,0,0,0,0,0,0,0 ; Up arrow key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db 0ah,0,0,0,0,0,0,0 ; Down arrow key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db 08h,0,0,0,0,0,0,0 ; Left arrow key db 0,0,0,0,0,0,0,0 db 0 ; termination byte db 0Ch,0,0,0,0,0,0,0 ; Right arrow key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '0',0,0,0,0,0,0,0 ; 0 keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '1',0,0,0,0,0,0,0 ; ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ;::: Micro Cornucopia Magazine DmC::: ;::: PO Box 223 Thanks to Robert Aprato for getting ::: ;::: Bend Oregon 97709 us the source..This version orignally ::: ;::: modified for Kaypro by Earl F. Weener ::: ;::: ::: ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::0,0,0,0,0 db 0 ; termination byte db 0dh,0,0,0,0,0,0,0 ; ENTER keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '.',0,0,0,0,0,0,0 ; . keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte end **************** ; ; NOCOMS EQU FALSE ;TRUE, NO .COM FILES SENT NOLBS EQU TRUE ;TRUE, NO .??# FILES SENT ; ;************************************************************************** ;*** If ZCPR does not allow renaming then this will prevent twits from *** ;*** sending a .COM file that could do nasties and running it *** ;************************************************************************** ; NOCOMR EQU FALSE ;TRUE, CHANGE.COM TO.OBJ ON RECEIVE ; ;******************************1 keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '2',0,0,0,0,0,0,0 ; 2 keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '3',0,0,0,0,0,0,0 ; 3 keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '4',0,0,0,0,0,0,0 ; 4 keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '5',0,0,0,0,0,0,0 ; 5 keypad key translate db 0,0,0,0,0,0,0,0 db 0 ; termination byte db '6',0,0,0,0,0,0,0 ; 6 keypad key tran:::: ; FALSE EQU 0 TRUE EQU NOT FALSE ; ;----------------------------------------------------- ; --- Conditional Assembly Options --- ; ;------------------------------------------------------ ; ;*** Kaypro runs standard CP/M ******************************************** ; STDCPM EQU TRUE ;TRUE, IS STANDARD CP/M ALTCPM EQU FALSE ;TRUE, IS TRS-80 OR H8 W/O 0-ORG ; ;************************************************************************** ;*** This is a little confusing but must have EXTM  ******************************************** ;*** Have you done the speed up? If so this is true else false for vanilla ;*** Kaypro *************************************************************** ; FASTCLK EQU TRUE ;PUT TRUE HERE FOR 4 MHZ CLOCK ; FRNTPNL EQU FALSE ;TO DISPLAY STATUS ON FRONT PANEL PANEL EQU 0FFH ;DEFAULT ADDRESS OF FRONT PANEL ; ;************************************************************************** ;*** Set to true to keep incoming files private (with BYE user # limit) *** MODEM DATA OUT PORT MODCTL2 EQU 06H ;SECOND CONTROL/STATUS PORT. ENDIF ;END OF EXTERNAL MODEM EQUATES ; ; --- End of Options --- ;------------------------------------------------------ ; ERRLIM EQU 10 ;MAX ALLOWABLE ERRORS (10 STANDARD) ; ;Define ASCII characters used ; SOH EQU 1 ;START OF HEADER EOT EQU 4 ;END OF TRANSMISSION ACK EQU 6 ;ACKNOWLEDGE NAK EQU 15H ;NEG ACKNOWLEDGE CRC EQU 'C' ;CRC REQUEST CHARACTER CAN EQU 18H ;CONTROL-X FOR CANCEL LF EQU 10 ;LINEFEED CR EQU 13 ;CARRIAGE R** I haven't tried this but i think it may cause problems if VOUT is *** ;*** true. **************************************************************** VOUT EQU FALSE ;TRUE, IF SECTOR COUNT TO CONSOLE ECHOFLG EQU 0008H ;ECHO ON/OFF FLAG FOR 'BYE', MUST BE AVAILABLE ;IF USING VOUT. ; ; ;------------------------------------------------------ ; --- Modem Port Equates --- ; ;------------------------------------------------------ ; ; ;If you are using an external modem (not S-100 plug-inlename from FCB2 to FCB1 ; CALL MOVEFCB ; ;Gobble up garbage chars from the line ;prior to receive or send ; IN MODDATP IN MODDATP ; ;Jump to appropriate function ; POP PSW ;GET OPTION IF LOGCAL PUSH PSW ;BUT SAVE IT ENDIF ; CPI 'S' ;SEND.. JZ SENDFIL ;..A FILE? ; CPI 'R' ;RECEIVE.. JZ RCVFIL ;..A FILE? ; ;Invalid option ; OPTNERR CALL ERXIT ;EXIT W/ERROR DB '++INVALID OPTION ON XMODEM ' DB 'COMMAND++',CR,LF DB 'Must be S for SEND; R or RC ' DB 'for RECEIVE',CR,LF ;************************************************************************** SETAREA EQU FALSE ;TRUE, IF USING DESIGNATED AREA TO RECEIVE RECU EQU 9 ;USER AREA TO REC IN (NOT GREATER THAN 9) DEFDRV EQU 'B' ;DRIVE TO REC TO ; ;************************************************************************** ; FILE TRANSFER LOGGING OPTIONS (J. Riley) *** ; Sorry folks this requires a macro library that I don't have. Anybody *** ; that finds a copy should send it in. "SEQIO22.???" (SenETURN ; IF STDCPM BASE EQU 0 ;CP/M BASE ADDRESS ENDIF ; IF ALTCPM BASE EQU 4200H ;ALTERNATE CP/M BASE ADDRESS ENDIF ; ORG BASE+100H ; ; ;Init private stack BEGIN LXI H,0 ;HL=0 DAD SP ;HL=STACK FROM CP/M SHLD STACK ;..SAVE IT LXI SP,STACK ;SP=MY STACK ; if setarea mvi e,0ffh ;get the current user area a 01/06/82 mvi c,user ;a 01/06/82 call bdos ;a 01/06/82 sta olduser ;save user number here a 01/06/82 mvi c,curdrv ;get the current drive a 01/06/82 cal) ;change these equates for your modem port requirements ; ;** Set up for Kaypro using serial data port ****************************** ; IF EXTMOD MODCTLP EQU 06H ;PUT YOUR MODEM STATUS PORT HERE MODSNDB EQU 04H ;YOUR BIT TO TEST FOR SEND MODSNDR EQU 04H ;YOUR VALUE WHEN READY MODRCVB EQU 01H ;YOUR BIT TO TEST FOR RECEIVE MODRCVR EQU 01H ;YOUR VALUE WHEN READY MODDCDB EQU 08H ;CARRIER DETECT BIT MODDCDA EQU 08H ;VALUE WHEN ACTIVE MODDATP EQU 04H ;YOUR MODEM DATA IN PORT MODDATO EQU 04H ;YOUR ,'$' IF LOGCAL MACLIB SEQIO22 BSIZE EQU 80H FILERR SET EXIT BUFFERS SET DBUF ; THE FOLLOWING ALLOCATIONS ARE USED BY THE 'FILE' MACROS DEFAULT$USER: DB LASTUSR CUR$USER: DB 0FFH DEFAULT$DISK: DB DEFDRV-'A' CUR$DISK: DB 0FFH PGSIZE: DW 0 LOGCALL FILE INFILE,CALLERS,,LASTCALR,,BSIZE,,PUBLIC,TRUE MVI A,RECU STA DEFAULT$USER FILE APPEND,LOG,,LOG,SYS,BSIZE,,PUBLIC,TRUE POP PSW ; GET OPTION PUT LOG ; PUT IT OUT TO LOG LDA MSPEED ; GET SPEED FACTOR ADI '0'-5 ; MAGICd to MicroC) *** ;************************************************************************** LOGCAL EQU FALSE ;IF USING LOGGING OF XMODEM TRANSFERS LASTUSR EQU 15 ;USER AREA OF 'LASTCALR' FILE (IF 'LOGCAL' ONLY) ; ;*** Set for BYE version 3 DmC 5/30/84 ************************************ LSPEED EQU TRUE ;REPORT DIFFERENCES IN BAUD RATES IN PRINTOUT MSPEED EQU 003CH ;LOCATION OF CURRENT BAUD RATE FACTOR(set by BYE) ; ;************************************************************************** ;*l bdos ;a 01/06/82 sta olddrv ;save drive here a 01/06/82 endif ; CALL ILPRT ;PRINT: DB CR,LF DB 'XMODEM ver 5.1A [CRC capable] ',CR,LF,0 ; ;GET OPTION ; LDA FCB+2 ;SECONDARY OPTION? CPI 'C' ;CRC CHECKING REQUESTED? JNZ CHKOPTN ;NO, GO CHECK PRIMARY LDA FCB+1 ;GET PRIMARY OPTION CPI 'R' ;CRC VALID ONLY FOR RECEIVE JNZ OPTNERR ;PRT MSG, ABORT XRA A ;ZERO ACCUM STA CRCFLG ;TURN ON CRC FLAG ; CHKOPTN LDA FCB+1 ;GET OPTION (S or R) PUSH PSW ;SAVE OPTION ; ;Move the fi   NUMBER FOR KAYPRO-II SO WE CAN PUT LOG ; PUT OUT A SINGLE LETTER CODE MVI A,' ' ; PUT LOG ; LDA PGSIZE ; NOW THE PROGRAM SIZE(IN MINUTES TRANSFER TIME) CALL PNDEC MVI A,' ' ; BLANK PUT LOG ; LOG THE DRIVE AND USER AREA AS A PROMPT LDA FCB ORA A JNZ WDRV MVI C,25 CALL @BDOS INR A WDRV: ADI 'A'-1 PUT LOG MVI C,32 ; NOW THE USER AREA(AS DECIMAL NUMBER) MVI E,0FFH CALL @BDOS CALL PNDEC MVI A,'>' ; MAKE IT LOOK LIKE A PROMPT PUT LOG LXI H,FCB+1 ; NOW THE NA person doing "MODEM S FN.FT". ;Can be invoked by 'XMODEM R FN.FT' or ;by 'XMODEM RC FN.FT' if CRC is to be used. ; RCVFIL CALL TRAP ;CHECK FOR NO NAME OR AMBIG. NAME ; IF NOCOMR LXI H,FCB+9 ;POINT TO FILETYPE MVI A,'C' ;1ST LETTER CMP M ;IS IT C ? JNZ CONTINU ;IF NOT, CONTINUE NORMALLY INX H ;GET 2ND LETTER MVI A,'O' ;2ND LETTER CMP M ;IS IT O ? JNZ CONTINU ;IF NOT, CONTINUE NORMALLY INX H ;GET 3RD LETTER MVI A,'M' ;3RD LETTER CMP M ;IS IT M ? JNZ CONTINU ;IF NOT, CONTINUE NOtor at a ;time with headers and checksums, and re- ;transmission on errors. ; SENDFIL CALL TRAP ;CHECK FOR NO NAME OR AMBIG. NAME CALL CNREC ;COMPUTE # OF RECORDS. CALL OPENFIL ;OPEN THE FILE MVI E,80 ;WAIT 80 SEC.. CALL WAITNAK ;..FOR INITIAL NAK ; SENDLP CALL RDSECT ;READ A SECTOR JC SENDEOF ;SEND EOF IF DONE CALL INCRSNO ;BUMP SECTOR # XRA A ;ZERO ERROR.. STA ERRCT ;..COUNT ; SENDRPT CALL SENDHDR ;SEND A HEADER CALL SENDSEC ;SEND DATA SECTOR LDA CRCFLG ;GET CRC FLAG ORA A * * * * ; ;----> TRAP: Check for no file name or ambiguous name ; TRAP LXI H,FCB+1 ;POINT TO FILE NAME MOV A,M ;GET FIRST CHAR OF FILE NAME CPI ' ' ;ANY THERE? JNZ ATRAP ;YES, CHECK FOR AMBIGOUS FILE NAME CALL ERXIT ;PRINT MSG, EXIT DB '++NO FILE NAME SPECIFIED++',CR,LF,'$' ; ATRAP MVI B,11 ;11 CHARS TO CHECK ; TRLOOP MOV A,M ;GET CHAR FROM FCB CPI '?' ;AMBIGUOUS? JZ TRERR ;YES, EXIT WITH ERROR MSG INX H ;POINT TO NEXT CHAR DCR B ;ONE LESS TO GO JNZ TRLOOP ;NOT DONE, CHECK SOME MME OF THE FILE MVI B,11 CALL PUTSTR MVI A,' ' ; BLANK PUT LOG CLOOP: GET CALLERS ; AND THE CALLER CPI EOF JZ QUIT PUT LOG JMP CLOOP PNDEC: CPI 10 ; TWO COLUMN DECIMAL FORMAT ROUTINE JC ONE ; ONE OR TWO DIGITS TO AREA #? JMP TWO ONE: PUSH PSW MVI A,'0' PUT LOG POP PSW TWO: MVI H,0 MOV L,A CALL DECOT RET DECOT: PUSH B PUSH D PUSH H LXI B,-10 LXI D,-1 ; DECOT2: DAD B INX D JC DECOT2 LXI B,10 DAD B XCHG MOV A,H ORA L CNZ DECOT MOV A,E RMALLY CALL ILPRT ; PRINT RENAMING MESSAGE DB 'Auto Renaming Filetype To ".OBJ" ' DB CR,LF,CR,LF,0 ; LXI H,OBJEXT LXI D,FCB+9 MVI B,3 ALTEXT MOV A,M STAX D INX H INX D DCR B JNZ ALTEXT JMP CONTINU OBJEXT DB 'OBJ' ENDIF ; CONTINU CALL CHEKFIL ;SEE IF FILE EXISTS CALL MAKEFIL ;..THEN MAKE NEW CALL ILPRT ;PRINT: ; if setarea db 'NOTE: File Will Be Received On',cr,lf ; a 01/06/81 db 'Drive ',defdrv,' User ',recu+30H,cr,lf ; tell this .a 01/06/81 endif ; DB;CRC IN EFFECT? CZ SENDCRC ;YES, SEND CRC CNZ SENDCKS ;NO, SEND CKSUM CALL GETACK ;GET THE ACK JC SENDRPT ;REPEAT IF NO ACK JMP SENDLP ;LOOP UNTIL EOF ; ;File sent, send EOT's ; SENDEOF MVI A,EOT ;SEND.. CALL SEND ;..AN EOT CALL GETACK ;GET THE ACK JC SENDEOF ;LOOP IF NO ACK JMP EXITLG ;ALL DONE ; * * * * * * * * * * * * * * * * * * * * * * * * RCVFIL: RECEIVE A FILE * * * * * * * * * * * * * * * * * * * * * * * * ; ;Receives a file in block format as sent ;by anotherORE RET ;NO AMBIGUOUS NAME, RETURN ; TRERR CALL ERXIT ;PRINT MSG, EXIT DB '++CAN''T USE WILD CARD OPTIONS++',CR,LF,'$' ; ;----> RCVSECT: Receive a sector ; ;Returns with carry set if EOT received. ; RCVSECT XRA A ;GET 0 STA ERRCT ;INIT ERROR COUNT ; RCVRPT: IF PMMI OR H8 OR DCH XRA A ;GET 0 STA ERRCDE ;CLEAR RECEIVE ERROR CODE ENDIF ; MVI B,10 ;10 SEC TIMEOUT CALL RECV ;GET SOH/EOT JC RCVSTOT ;TIMEOUT ; IF PMMI OR H8 OR DCH CALL RCVERR ;TRANS ERROR? JC RCVSERR ;CARRY S ADI '0' PUT LOG POP H POP D POP B RET PUTSTR: MOV A,M PUSH H PUSH B PUT LOG POP B POP H INX H DCR B JNZ PUTSTR RET QUIT: FINIS LOG JMP EXIT ENDIF ; LOGCAL ; * * * * * * * * * * * * * * * * * * * * * * * * SENDFIL: SENDS A CP/M FILE * * * * * * * * * * * * * * * * * * * * * * * * ; ;The CP/M file specified in the XMODEM command ;is transferred over the phone to another ;computer running MODEM with the "R" (receive) ;option. The data is sent one sec 'FILE OPEN - READY TO RECEIVE',CR,LF,0 ; RCVLP CALL RCVSECT ;GET A SECTOR JC RCVEOT ;GOT EOT CALL WRSECT ;WRITE THE SECTOR CALL INCRSNO ;BUMP SECTOR # CALL SENDACK ;ACK THE SECTOR JMP RCVLP ;LOOP UNTIL EOF ; ;Got EOT on sector - flush buffers, end ; RCVEOT CALL WRBLOCK ;WRITE THE LAST BLOCK CALL SENDACK ;ACK THE SECTOR CALL CLOSFIL ;CLOSE THE FILE JMP EXITLG ;ALL DONE ; * * * * * * * * * * * * * * * * * * * * * * * * SUBROUTINES * * * * * * * * * * * * * * * * * * * *   ET IF ERROR ENDIF ; CPI SOH ;GET SOH? JZ RCVSOH ;..YES ; ;Earlier versions of MODEM program send some nulls - ;ignore them ; ORA A ;00 FROM SPEED CHECK? JZ RCVRPT ;YES, IGNORE IT CPI EOT ;END OF TRANSFER? STC ;RETURN WITH CARRY.. RZ ;..SET IF EOT ; ;Didn't get SOH or EOT - ; -or- ;Didn't get valid header - purge the line, ;then send NAK. ; RCVSERR MVI B,1 ;WAIT FOR 1 SEC.. CALL RECV ;..WITH NO CHARS JNC RCVSERR ;LOOP UNTIL SENDER DONE LDA CRCFLG ;GET CRC FLAG ORA A ;CR 1 SEC CALL RECV ;GET CMA'D SECT # JC RCVSTOT ;TIMEOUT ; IF PMMI OR H8 OR DCH CALL RCVERR ;TRANS ERROR? JC RCVSERR ;CARRY SET IF ERROR ENDIF ; CMA ;CALC COMPLEMENT CMP D ;GOOD SECTOR #? JZ RCVDATA ;YES, GET DATA ; ;Got bad sector # ; JMP RCVSERR ;BUMP ERROR CT. ; RCVDATA MOV A,D ;GET SECTOR # STA RCVSNO ;SAVE IT MVI C,0 ;INIT CKSUM CALL CLRCRC ;CLEAR CRC COUNTER LXI H,BASE+80H ;POINT TO BUFFER ; RCVCHR MVI B,1 ;1 SEC TIMEOUT CALL RECV ;GET CHAR JC RCVSTOT ;TIMEOUT  DB '++CAN''T DELETE RECEIVED FILE++',CR,LF,'$',0 ; ;Timed out on receive ; RCVSTOT JMP RCVSERR ;BUMP ERR CT, ETC. ; ;---->RCVERR: Checks to see if framing error, overrun, or ; parity error occurred. ; 1. Error code (ERRCDE) was set in recv routine ; 2. ERRCDE=0 for no errors, ERRCDE<>0 for errors ; 3. If there has been an error, this routine sets ; the carry bit on. ; IF PMMI OR H8 OR DCH RCVERR PUSH PSW ;SAVE CHAR TRANSMITTED LDA ERRCDE ;GET RECEIVE ERR CODE ANA A ;IS IT ZERO? JZ RC ; send a NAK requesting the sector be ; resent. ; RCVCRC MVI E,2 ;NUMBER OF BYTES TO RECEIVE ; RCVCRC2 MVI B,1 ;1 SEC TIMEOUT CALL RECV ;GET CRC BYTE JC RCVSTOT ;TIMEOUT ; IF PMMI OR H8 OR DCH CALL RCVERR ;TRANSMISSION ERROR? JC RCVSERR ;YES, IF CARRY IS ON ENDIF ; DCR E ;DECREMENT NUM OF BYTES JNZ RCVCRC2 ;GET BOTH BYTES CALL CHKCRC ;CHECK RCVD CRC AGAINST CALC'D CRC ORA A ;IS CRC OKAY? JZ CHKSNUM ;YES, GO CHECK SECTOR NUMBERS JMP RCVSERR ;GO CHECK ERROR LIMIT AND SEND NAKC IN EFFECT? MVI A,NAK ;PUT NAK IN ACCUM JNZ RCVSER2 ;NO, SEND THE NAK LDA FIRSTIME;GET FIRST TIME SWITCH ORA A ;HAS FIRST SOH BEEN RECEIVED? MVI A,NAK ;PUT NAK IN ACCUM JZ RCVSER2 ;YES, THEN SEND NAK MVI A,CRC ;TELL SENDER CRC IS IN EFFECT ; RCVSER2 CALL SEND ;..THE NAK or CRC request LDA ERRCT ;ABORT IF.. INR A ;..WE HAVE REACHED.. STA ERRCT ;..THE ERROR.. CPI ERRLIM ;..LIMIT? JC RCVRPT ;..NO, TRY AGAIN ; ;10 errors in a row - ; RCVSABT CALL CLOSFIL ;KEEP WHATEVER WE GOT CA; IF PMMI OR H8 OR DCH CALL RCVERR ;TRANS ERROR? JC RCVSERR ;CARRY SET IF ERROR ENDIF ; MOV M,A ;STORE CHAR INR L ;DONE? JNZ RCVCHR ;NO, LOOP LDA CRCFLG ;GET CRC FLAG ORA A ;CRC IN EFFECT? JZ RCVCRC ;YES, TO RECEIVE CRC ; ;Verify checksum ; MOV D,C ;SAVE CHECKSUM MVI B,1 ;TIMEOUT LEN. CALL RECV ;GET CHECKSUM JC RCVSTOT ;TIMEOUT ; IF PMMI OR H8 OR DCH CALL RCVERR ;TRANS ERROR? JC RCVSERR ;CARRY SET IF ERROR ENDIF ; CMP D ;CHECKSUM OK? JNZ RCVSERR ;NO, ERROR ; VERR2 ;YES, NO ERROR POP PSW ;RESTORE CHAR TRANSMITTED STC ;SET CARRY ON FOR ERROR RET ; RCVERR2 POP PSW ;RESTORE CHAR TRANSMITTED ORA A ;CLEAR CARRY BIT RET ENDIF ; ;Got SOH - get block #, block # complemented ; RCVSOH XRA A ;ZERO ACCUM STA FIRSTIME;INDICATE FIRST SOH RECV'D MVI B,1 ;TIMEOUT = 1 SEC CALL RECV ;GET SECTOR JC RCVSTOT ;GOT TIMEOUT ; IF PMMI OR H8 OR DCH CALL RCVERR ;TRANS ERROR? JC RCVSERR ;CARRY SET IF ERROR ENDIF ; MOV D,A ;D=BLK # MVI B,1 ;TIMEOUT = ; ;Previous sector repeated, due to the last ACK ;being garbaged. ACK it so sender will catch up ; RECVACK CALL SENDACK ;SEND THE ACK, JMP RCVSECT ;GET NEXT BLOCK ; ;Send an ACK for the sector ; SENDACK MVI A,ACK ;GET ACK CALL SEND ;..AND SEND IT RET ; ;----> SENDHDR: Send the sector header ; ;SEND: (SOH) (block #) (complemented block #) ; SENDHDR MVI A,SOH ;SEND.. CALL SEND ;..SOH, LDA SECTNO ;THEN SEND.. CALL SEND ;..SECTOR # LDA SECTNO ;THEN SECTOR # CMA ;..COMPLEMENTEDLL ILPRT DB '++UNABLE TO RECEIVE BLOCK ' DB '- ABORTING++',CR,LF,0 CALL DELFILE ;DELETE RECEIVED FILE ; v48c smh CALL ILPRT ;PRINT SECOND HALF OF MESSAGE DB '++INCOMPLETELY RECEIVED FILE ' DB 'DELETED++',CR,LF,0 JMP EXIT ;GIVE UP ; ;----> DELFILE: Deletes the received file (used if receive aborts) ; ; v48c smh DELFILE LXI D,FCB ;POINT TO FILE ; (whole routine) MVI C,ERASEF ;GET FUNCTION CALL BDOS ;DELETE IT INR A ;DELETE OK? RNZ ;..YES, RETURN CALL ERXIT ;..NO, ABORT ;Got a sector, it's a duplicate if = previous, ; or OK if = 1 + previous sector ; CHKSNUM LDA RCVSNO ;GET RECEIVED MOV B,A ;SAVE IT LDA SECTNO ;GET PREV CMP B ;PREV REPEATED? JZ RECVACK ;ACK TO CATCH UP INR A ;CALC NEXT SECTOR # CMP B ;MATCH? JNZ ABORT ;NO MATCH - STOP SENDER, EXIT RET ;CARRY OFF - NO ERRORS ; ;----> RCVCRC: Receive the cyclic redundancy check ; characters (2 bytes), and see if the crc ; received matches the one calculated. ; If they match, get next sector, else !  .. CALL SEND ;..SECTOR # RET ;FROM SENDHDR ; ;----> SENDSEC: Send the data sector ; SENDSEC MVI C,0 ;INIT CKSUM CALL CLRCRC ;CLEAR THE CRC COUNTER LXI H,BASE+80H ;POINT TO BUFFER ; SENDC MOV A,M ;GET A CHAR CALL SEND ;SEND IT INR L ;POINT TO NEXT CHAR JNZ SENDC ;LOOP IF <100H RET ;FROM SENDSEC ; ;----> SENDCKS: Send the checksum ; SENDCKS MOV A,C ;SEND THE.. CALL SEND ;..CHECKSUM RET ;FROM SENDCKS ; ;----> SENDCRC: Send the two Cyclic Redundancy ; Check characters. CalH ORA L CNZ DECOUTX MOV A,E ADI '0' CALL CTYPE POP H POP D POP B RET ; ;----> CHEKFIL: See if file exists ; ;If it exists, say use a different name. ; CHEKFIL if setarea call recarea ;set the designated area up a 01/06/81 endif ; LXI D,FCB ;POINT TO CTL BLOCK MVI C,SRCHF ;SEE IF IT.. CALL BDOS ;..EXISTS INR A ;FOUND? RZ ;..NO, RETURN CALL ERXIT ;EXIT, PRINT ERROR MESSAGE DB '++FILE EXISTS - USE A DIFFERENT NAME++' DB CR,LF,'$' ; ;----> MAKEFIL: Makes the GETATOT JMP ACKERR ;NO MSG ; ABORT LXI SP,STACK ; ABORTL MVI B,1 ;1 SEC. W/O CHARS. CALL RECV JNC ABORTL ;LOOP UNTIL SENDER DONE MVI A,CAN ;CONTROL X CALL SEND ;STOP SENDING END ; ABORTW MVI B,1 ;1 SEC W/O CHARS. CALL RECV JNC ABORTW ;LOOP UNTIL SENDER DONE MVI A,' ' ;GET A SPACE... CALL SEND ;TO CLEAR OUT CONTROL X CALL ERXIT ;EXIT WITH ABORT MSG DB 'XMODEM PROGRAM CANCELLED',CR,LF,'$' ; ;----> INCRSNO: Increment sector # ; INCRSNO LDA SECTNO ;INCR.. INR A ;..SECT.. STARD COUNT OF MAX EXTENT SEEN MOV E,A ;SAVE IT IN DE DAD H DAD H ;MULTIPLY # OF EXTENTS - 1 DAD H ; TIMES 128 DAD H DAD H DAD H DAD H DAD D ;ADD IN SIZE OF LAST EXTENT SHLD RCNT ;SAVE TOTAL RECORD COUNT RET ;AND EXIT ; ;POINT TO DIRECTORY ENTRY SOME DCR A ;UNDO PREV 'INR A' ANI 3 ;MAKE MODULUS 4 ADD A ;MULTIPLY... ADD A ;..BY 32 BECAUSE ADD A ;..EACH DIRECTORY ADD A ;..ENTRY IS 32 ADD A ;..BYTES LONG LXI H,BASE+80H ;POINT TO BUFFER ADD L ;POINT TO ENTRY ADI 15 ;OFFl FINCRC ; to calc the CRC which will be in ; d,e regs upon return. ; SENDCRC CALL FINCRC ;CALC THE CRC FOR THIS SECTOR MOV A,D ;PUT FIRST CRC BYTE IN ACCUM CALL SEND ;SEND IT MOV A,E ;PUT SECOND CRC BYTE IN ACCUM CALL SEND ;SEND IT XRA A ;SET ZERO RETURN CODE RET ; ;----> GETACK: Get the ACK on the sector ; ;Returns with carry clear if ACK received. ;If an ACK is not received, the error count ;is incremented, and if less than "ERRLIM", ;carry is set and control returns. If the  file to be received ; MAKEFIL XRA A ;SET EXT & REC # TO 0 STA FCBEXT STA FCBSNO LXI D,FCB ;POINT TO FCB MVI C,MAKE ;GET BDOS FNC CALL BDOS ;TO THE MAKE INR A ;FF=BAD? RNZ ;OPEN OK ;Directory full - can't make file CALL ERXIT DB '++ERROR - CAN''T MAKE FILE++',CR,LF DB 'Directory must be full',CR,LF,'$' ; ;----> CNREC: Computes record count, and saves it ; until successful file OPEN. ; ;LOOK UP THE FCB IN THE DIRECTORY CNREC MVI A,'?' ;MATCH ALL EXTENTS STA FCBEXT MVI SECTNO ;..NUMBER IF VOUT ;CK FOR OPTIONAL COUNT TO CONSOLE PUSH PSW ; PUSH H ; XRA A ;A=0 STA ECHOFLG ;ECHO.FLAG = A, (OFF) MVI A,CR ; CALL CTYPE ; LHLD SECCNT ;UPDATE TOTAL SECTOR COUNT INX H ; SHLD SECCNT ; CALL DECOUTX ;DISPLAY COUNT MVI A,0FFH ;A=-1 STA ECHOFLG ;ECHO.FLAG = A, (ON) POP H ; POP PSW ; ENDIF ;VOUT RET ; ; DECOUTX PUSH B PUSH D PUSH H LXI B,-10 LXI D,-1 ; DECOU2X DAD B INX D JC DECOU2X LXI B,10 DAD B XCHG MOV A,SET TO RECORD COUNT MOV L,A ;HL NOW POINTS TO REC COUNT MOV B,M ;GET RECORD COUNT DCX H DCX H ;BACK DOWN TO EXTENT NUMBER DCX H LDA MAXEXT ;COMPARE WITH CURRENT MAX. ORA A ;IF NO MAX YET JM BIGGER ;THEN SAVE RECORD COUNT ANYWAY CMP M JNC MOREDIR ; BIGGER: MOV A,B ;SAVE NEW RECORD COUNT STA RCNT MOV A,M ;SAVE NEW MAX. EXTENT NO. STA MAXEXT JMP MOREDIR ;GO FIND MORE EXTENTS ; ;----> OPENFIL: Opens the file to be sent ; OPENFIL XRA A ;SET EXT & REC # TO 0 FOR PROPER OPEN STA;error count is at "ERRLIM", the program ;aborts. ; GETACK MVI B,10 ;WAIT 10 SECONDS MAX CALL RECVDG ;RECV W/GARBAGE COLLECT JC GETATOT ;TIMED OUT CPI ACK ;OK? (CARRY OFF IF =) RZ ;YES, RET FROM GETACK ; ;Timeout or error on ACK - bump error count ; ACKERR LDA ERRCT ;GET COUNT INR A ;BUMP IT STA ERRCT ;SAVE BACK CPI ERRLIM ;AT LIMIT? RC ;NOT AT LIMIT ; ;Reached error limit ; CSABORT CALL ERXIT DB '++CAN''T SEND SECTOR ' DB '- ABORTING++',CR,LF,'$' ; ;Timeout getting ACK ; A,0FFH STA MAXEXT ;INIT MAX EXT NO. MVI C,SRCHF ;GET 'SEARCH FIRST' FNC LXI D,FCB CALL BDOS ;READ FIRST INR A ;WERE THERE ANY? JNZ SOME ;GOT SOME CALL ERXIT DB '++FILE NOT FOUND++$' ; ;READ MORE DIRECTORY ENTRIES MOREDIR MVI C,SRCHN ;SEARCH NEXT LXI D,FCB CALL BDOS ;READ DIR ENTRY INR A ;CHECK FOR END (0FFH) JNZ SOME ;NOT END OF DIR...PROCESS EXTENT LDA MAXEXT ;HIT END...GET HIGHEST EXTENT NO. SEEN MOV L,A ;WHICH GIVES EXTENT COUNT - 1 MVI H,0 MOV D,H LDA RCNT ;GET RECO"   FCBEXT STA FCBSNO LXI D,FCB ;POINT TO FILE MVI C,OPEN ;GET FUNCTION CALL BDOS ;OPEN IT INR A ;OPEN OK? JNZ OPENOK ;..YES CALL ERXIT ;..NO, ABORT DB '++OPEN ERROR++',CR,LF,'$' ; ;Check for distribution-protected file ; OPENOK LDA FCB+1 ;FIRST CHAR OF FILE NAME ANI 80H ;CHECK BIT 7 JNZ OPENOT ;If on, file can't be sent. LDA FCB+2 ;Also check "f2" for tag. ANI 80H ;Is it set? JZ OPENOK2 ;If not, ok to send file. ; OPENOT CALL ERXIT ;EXIT W/MESSAGE DB '++THIS FILE IS NOT FOR DLL ILPRT DB ' secs to send at 300 baud).',cr,lf ; v48b bhk db '[Control-X to cancel.]',cr,lf,0 ; v48c bhk RET ; ;----> DIVHL14: Divides HL by 14, ; UPON EXIT: L=QUOTIENT,H=REMAINDER ; divhl14 push b MVI B,8 ;SHIFT FACTOR TO B MVI C,14 ;DIVISOR TO C div2 xra a ; clear carry flag and accumulator DAD H MOV A,H SUB C JM DIV3 ;DONT BORROW ON NEG RESULTS MOV H,A MOV A,L ORI 1 ;BORROW 1 MOV L,A DIV3 dcr b jnz div2 pop b ret ; ;----> CLOSFIL: Closes the received file ;  DB ' Hex) Sectors',CR,LF ; v48b bhk db '(approximately ',0 ; v48b bhk lhld rcnt ; get # of sectors ; v48b bhk IF LSPEED LDA MSPEED ; V50 JPR CPI B1200 ; " PUSH PSW ; " JNZ S300 ; " XRA A ; DIVIDE HL BY 2 " MOV A,H ; " RAR ; " MOV H,A ; " MOV A,L ; " RAR ; " MOV L,A ; " XRA A ; DIVIDE HL BY 2 " MOV A,H ; " RAR ; " MOV H,A ; " MOV A,L ; " RAR ; " MOV L,A ; " S300  LXI D,BASE+80H ;TO DATA CALL MOVE128 ;MOVE TO BUFFER SHLD SECPTR ;SAVE BUFFER POINTER RET ;FROM "READSEC" ; ;Buffer is empty - read in another block of 16 ; RDBLOCK LDA EOFLG ;GED EOF FLAG CPI 1 ;IS IT SET? STC ;TO SHOW EOF RZ ;GOT EOF MVI C,0 ;SECTORS IN BLOCK LXI D,DBUF ;TO DISK BUFFER ; RDSECLP PUSH B PUSH D MVI C,STDMA ;SET DMA.. CALL BDOS ;..ADDR LXI D,FCB MVI C,READ CALL BDOS POP D POP B ORA A ;READ OK? JZ RDSECOK ;YES DCR A ;EOF? JZ REOF ;GOT EOF ; ISTRIBUTION, SORRY++' DB CR,LF,'$' ; OPENOK2 EQU $ ; IF NOLBS OR NOCOMS ;CHECK FOR SEND RESTRICTIONS LXI H,FCB+11 MOV A,M ;CHECK FOR PROTECT ATTR ANI 7FH ;REMOVE CP/M 2.x ATTRS ENDIF ;NOLBS OR NOCOMS ; IF NOLBS ;DON'T ALLOW '#' TO BE SENT. CPI '#' ;CHK FOR '#' AS LAST FIRST JZ OPENOT ;IF '#', CAN'T SEND, SHOW WHY ENDIF ;NOLBS ; IF NOCOMS ;DON'T ALLOW .COM TO BE SENT CPI 'M' ;IF NOT, CHK FOR '.COM' JNZ OPENOK3 ;IF NOT, OK TO SEND DCX H MOV A,M ;CHK NEXT CHAR ANI 7FH ;STCLOSFIL LXI D,FCB ;POINT TO FILE MVI C,CLOSE ;GET FUNCTION CALL BDOS ;CLOSE IT INR A ;CLOSE OK? RNZ ;..YES, RETURN CALL ERXIT ;..NO, ABORT DB '++CAN''T CLOSE FILE++',CR,LF,'$' ; ; ;----> DECOUT: Decimal output routine ; DECOUT: PUSH B PUSH D PUSH H LXI B,-10 LXI D,-1 ; DECOU2: DAD B INX D JC DECOU2 LXI B,10 DAD B XCHG MOV A,H ORA L CNZ DECOUT MOV A,E ADI '0' CALL CTYPE POP H POP D POP B RET ; ;----> DHXOUT: - double precision hex output routine. ;ENDIF call divhl14 ; divide HL by 14 (sectors/min) ; v48b bhk PUSH H IF LOGCAL SHLD PGSIZE ; V50 JPR ENDIF MVI H,0 call decout ; print decimal # of minutes ; v48b bhk call ilprt ; v48b bhk db ' mins, ',0 POP H MOV A,H ;REMAINDER X 4 = SECONDS RLC RLC MOV L,A MVI H,0 CALL DECOUT IF LSPEED POP PSW ; V50 JPR JNZ MS300 CALL ILPRT DB ' secs to send at 1200 baud).',cr,lf ; v48b bhk db '[Control-X to cancel.]',cr,lf,0 ; v48c bhk RET MS300 ENDIF CA;Read error ; CALL ERXIT DB '++FILE READ ERROR++',CR,LF,'$' ; RDSECOK LXI H,80H ;ADD LENGTH OF ONE SECTOR... DAD D ;...TO NEXT BUFF XCHG ;BUFF TO DE INR C ;MORE SECTORS? MOV A,C ;GET COUNT CPI 16 ;DONE? JZ RDBFULL ;..YES, BUFF IS FULL JMP RDSECLP ;READ MORE ; REOF MVI A,1 STA EOFLG ;SET EOF FLAG MOV A,C ; ;Buffer is full, or got EOF ; RDBFULL STA SECINBF ;STORE SECTOR COUNT LXI H,DBUF ;INIT BUFFER.. SHLD SECPTR ;..POINTER LXI D,BASE+80H ;RESET.. MVI C,STDMA ;..DMA.. RIP ATTRIBUTES CPI 'O' ; 'O'? JNZ OPENOK3 ;IF NOT, OK TO SEND DCX H MOV A,M ;NOW CHK FIRST CHAR ANI 7FH ;STRIP ATTRIBUTES CPI 'C' ; 'C' AS IN '.COM'? JNZ OPENOK3 ;IF NOT, CONTINUE CALL ERXIT ;EXIT W/MESSAGE DB '++CAN''T SEND A .COM FILE++' DB CR,LF,'$' ENDIF ;NOCOMS ; OPENOK3 CALL ILPRT ;PRINT: DB 'File Open - ',0 ; v48b bhk LHLD RCNT ; Get record count. CALL DECOUT ;PRINT DECIMAL NUMBER OF SECTORS CALL ILPRT DB ' (',0 CALL DHXOUT ;Now print size in hex. CALL ILPRT  Call with hex value in HL. ; DHXOUT PUSH H ;Save H,L PUSH PSW ;Save A MOV A,H ;Get MS byte. CALL HEXO ;Output hi order byte. MOV A,L ;Get LS byte. CALL HEXO ;Output lo order byte. POP PSW ;Restore A POP H ;Restore H,L RET ;Return to caller. ; ; ;----> RDSECT: Reads a sector ; ;For speed, this routine buffers up 16 ;sectors at a time. ; RDSECT LDA SECINBF ;GET # SECT IN BUFF. DCR A ;DECREMENT.. STA SECINBF ;..IT JM RDBLOCK ;EXHAUSTED? NEED MORE. LHLD SECPTR ;GET POINTER #   CALL BDOS ;..ADDR JMP RDSECT ;PASS SECT TO CALLER ; ;----> WRSECT: Write a sector ; ;Writes the sector into a buffer. When 16 ;have been written, writes the block to disk. ; ;Entry point "WRBLOCK" flushes the buffer at EOF. ; WRSECT LHLD SECPTR ;GET BUFF ADDR XCHG ;TO DE FOR MOVE LXI H,BASE+80H ;FROM HERE CALL MOVE128 ;MOVE TO BUFFER XCHG ;SAVE NEXT.. SHLD SECPTR ;..BLOCK POINTER LDA SECINBF ;BUMP THE.. INR A ;..SECTOR #.. STA SECINBF ;..IN THE BUFF CPI 16 ;HAVE WE 16? RNZ IF PMMI IN BAUDRP ;READ MODEM STATUS ENDIF ; IF PMMI AND FRNTPNL OUT PANEL ;DISPLAY STATUS ON PANEL LIGHTS ENDIF ; ANI MODDCDB ;CARRIER DETECT MASK CPI MODDCDA ;IS IT STILL ON? CNZ CARCK ;IF NOT, TEST FOR 15 SECONDS ; ;Modem timed out receiving - but carrier still on. ; POP D ;RESTORE D,E STC ;CARRY SHOWS TIMEOUT RET ; ;Got character from modem ; MCHAR: ;Check to see if there was a framing error, ;overrun, or parity error. ; IF PMMI OR H8 IN MODCTL2 ;GET MODEM STATU example, having just sent a sector, ;calling RECVDG will delete any line-noise-induced ;characters "long" before the ACK/NAK would ;be received. ; RECVDG EQU $ ;RECEIVE W/GARBAGE DELETE IN MODDATP ;GET A CHAR IN MODDATP ;..TOTALLY PURGE UART ; RECV PUSH D ;SAVE ; IF FASTCLK ;4MHZ? MOV A,B ;GET TIME REQUEST ADD A ;DOUBLE IT MOV B,A ;NEW TIME IN B ENDIF ; MSEC LXI D,50000 ;1 SEC DCR COUNT ; IF NOT DCH MWTI IN MODCTLP ;CHECK STATUS ENDIF ; IF DCH MWTI IN MODCTL2 ;CHECK STATUSthin 15 seconds, normal ;program execution continues. Else, it will abort ;to CP/M via EXIT. ; CARCK MVI E,150 ;VALUE FOR 15 SECOND DELAY ; CARCK1 CALL DELAY ;KILL .1 SECONDS ; IF EXTMOD OR H8 OR DCH IN MODCTL2 ;READ MODEM STATUS ENDIF ; IF PMMI IN BAUDRP ;READ MODEM STATUS ENDIF ; IF PMMI AND FRNTPNL OUT PANEL ;DISPLAY STATUS ENDIF ; ANI MODDCDB ;CARRIER DETECT MASK CPI MODDCDA ;IS IT STILL ON? RZ ;RETURN IF CARRIER ON DCR E ;HAS 15 SECONDS EXPIRED? JNZ CARCK1 ;IF NOT ;NO, RETURN ; ;----> WRBLOCK: Writes a block to disk ; WRBLOCK LDA SECINBF ;# SECT IN BUFFER ORA A ;0 MEANS END OF FILE RZ ;NONE TO WRITE MOV C,A ;SAVE COUNT LXI D,DBUF ;POINT TO DISK BUFF ; DKWRLP PUSH H PUSH D PUSH B MVI C,STDMA ;SET DMA CALL BDOS ;TO BUFFER LXI D,FCB ;THEN WRITE MVI C,WRITE ;..THE.. CALL BDOS ;..BLOCK POP B POP D POP H ORA A JNZ WRERR ;OOPS, ERROR LXI H,80H ;LENGTH OF 1 SECT DAD D ;HL= NEXT BUFF XCHG ;TO DE FOR SETDMA DCR C ;MORE SECTORS?S ENDIF ; IF DCH IN MODCTL2 ;GET MODEM STATUS ENDIF ; IF PMMI OR H8 OR DCH MOV D,A ;SAVE STATUS ANI MODFRME ;FRAMING ERROR? CPI MODFRME JNZ MCHAR2 ;NO, CHECK FOR OVERRUN LDA ERRCDE ;GET RECV ERR CODE ORI MODFRME ;TURN ON RECV ERR GODE STA ERRCDE ;PUT IT BACK ; MCHAR2: MOV A,D ;RESTORE MODEM STATUS ANI MODOVRE ;OVERRUN? CPI MODOVRE JNZ MCHAR3 ;NO, CHECK FOR PARITY ERROR LDA ERRCDE ORI MODOVRE ;TURN ON RECV ERR CODE STA ERRCDE ; MCHAR3: MOV A,D ;RESTORE MODEM STATUS  ENDIF ; IF PMMI AND FRNTPNL OUT PANEL ;DISPLAY STATUS ON PANEL LIGHTS ENDIF ; ANI MODRCVB ;ISOLATE BIT CPI MODRCVR ;READY? JZ MCHAR ;GOT CHAR DCR E ;COUNT.. JNZ MWTI ;..DOWN.. DCR D ;..FOR.. JNZ MWTI ;..TIMEOUT DCR B ;MORE SECONDS? JNZ MSEC ;YES, WAIT ; ;Test for the presence of carrier - if none, go to ;CARCK and continue testing for 15 seconds. If carrier ;returns, continue. If is doesn't return, exit. ; IF EXTMOD OR H8 OR DCH IN MODCTLP ;READ MODEM STATUS ENDIF ;, CONTINUE TESTING JMP EXIT ;ELSE, ABORT TO CP/M. ; ;DELAY - 100 millisecond delay. ; DELAY PUSH B ;SAVE B,C ; IF FASTCLK ;IF 4MHZ CLOCK LXI B,16667 ;VALUE FOR 100MS DELAY ENDIF ; IF NOT FASTCLK LXI B,8334 ;VALUE FOR 100MS DELAY ENDIF ; DELAY2 DCX B ;UPDATE COUNT MOV A,B ;GET MS BYTE ORA C ;COUNT = ZERO? JNZ DELAY2 ;IF NOT, CONTINUE POP B ;RESTORE B,C RET ;RETURN TO CARCK1. ; ;----> SEND: Send a character to the modem ; SEND PUSH PSW ;SAVE THE CHARACTER CALL UPDCRC ;ca JNZ DKWRLP ;..YES, LOOP XRA A ;GET A ZERO STA SECINBF ;RESET # OF SECTORS LXI H,DBUF ;RESET BUFFER.. SHLD SECPTR ;..POINTER ; RSDMA LXI D,BASE+80H ;RESET.. MVI C,STDMA ;..DMA.. CALL BDOS ;..ADDR RET ; WRERR CALL RSDMA ;RESET DMA TO NORM. MVI C,CAN ;CANCEL.. CALL SEND ;..SENDER CALL ERXIT ;EXIT W/MSG: DB '++ERROR WRITING FILE++',CR,LF,'$' ; ;----> RECV: Receive a character ; ;Timeout time is in B, in seconds. Entry via ;"RECVDG" deletes garbage characters on the ;line. For ANI MODPARE ;PARITY ERROR? CPI MODPARE JNZ MCHAR4 ;NO, GET DATA CHAR LDA ERRCDE ORI MODPARE STA ERRCDE ; MCHAR4: ENDIF ;PMMI OR H8 OR DCH ; ;Get data char ; IN MODDATP ;READ THE CHAR POP D ;RESTORE DE ; ;Calc checksum and CRC ; PUSH PSW ;SAVE THE CHAR CALL UPDCRC ;CALC CRC ADD C ;ADD TO CHECKSUM MOV C,A ;SAVE CHECKSUM POP PSW ;RESTORE CHAR ORA A ;CARRY OFF: NO ERROR RET ;FROM "RECV" ; ;CARCK - common 15 second carrier test for RECV and ;SEND. If carrier returns wi$  lc the crc ADD C ;CALC CKSUM MOV C,A ;SAVE CKSUM ; IF NOT DCH SENDW IN MODCTLP ;GET STATUS ENDIF ; IF DCH SENDW IN MODCTL2 ;GET STATUS ENDIF ; IF PMMI AND FRNTPNL OUT PANEL ;DISPLAY STATUS ENDIF ; ANI MODSNDB ;ISOLATE READY BIT CPI MODSNDR ;READY? JZ SENDR ;..YES, GO SEND ; ;Xmit status not ready, so test for carrier before ;looping - if lost, go to CARCK and give it up to 15 ;seconds to return. If it doesn't return abort via ;EXIT. ; PUSH D ;Save D,E ; IF EXTMOD OR .. RAR ;..JUSTIFY.. RAR ;..LEFT.. RAR ;..DIGIT.. CALL NIBBL ;PRINT LEFT DIGIT POP PSW ;RESTORE RIGHT ; NIBBL ANI 0FH ;ISOLATE DIGIT CPI 10 ;IS IT <10? JC ISNUM ;YES, NOT ALPHA ADI 7 ;ADD ALPHA BIAS ; ISNUM ADI '0' ;MAKE PRINTABLE JMP CTYPE ;..THEN TYPE IT ; ;----> ILPRT: Inline print of message ; ;The call to ILPRT is followed by a message, ;binary 0 as the end. ; ILPRT XTHL ;SAVE HL, GET HL=MSG ; ILPLP MOV A,M ;GET CHAR ORA A ;END OF MSG? JZ ILPRET ;..YES, RETURN CA;YES, SEND BLOCK CPI CRC ;CRC INDICATED? JZ WAITCRC ;YES, GO PUT CRC IN EFFECT CPI CAN ;WAS IT A CANCEL (CONTROL-X)? ; v48c bhk JZ ABORT ;YES, ABORT ; v48c bhk DCR E ;80 TRIES? JZ ABORT ;YES, ABORT JMP WAITNAK ;NO, LOOP ; ;----> WAITCRC: Turn on CRC Flag ; WAITCRC XRA A ;ZERO ACCUM STA CRCFLG ;TURN ON CRC OPT RET ; ;----> MOVEFCB: Moves FCB(2) to FCB ; ;In order to make the XMODEM command 'natural', ;i.e. XMODEM SEND FILENAME (MODEM S FN.FT) rather ;than XMODEM FILENAME SEND  01/06/81 mvi e,recu ;ok now set the user area ;a 01/06/81 RECARE mvi c,user ;tell bdos what we want to do ;a 01/06/81 call bdos ;do it ;a 01/06/81 RET ; RECDRV mvi e,defdrv-41h ;make drive cp/m number ;a 01/06/81 RECDRX mvi c,seldrv ;tell bdos ;a 01/06/81 call bdos ;do it ;a 01/06/81 ret ;back ;a 01/06/81 endif ; ;Move 128 characters ; MOVE128 MVI B,128 ;SET MOVE COUNT ; ;Move from (HL) to (DE) length in (B) ; MOVE MOV A,M ;GET A CHAR STAX D ;STORE IT INX H ;TOH8 OR DCH IN MODCTL2 ;READ MODEM STATUS ENDIF ; IF PMMI IN BAUDRP ;READ MODEM STATUS ENDIF ; IF PMMI AND FRNTPNL OUT PANEL ;DISPLAY STATUS ENDIF ; ANI MODDCDB ;CARRIER DETECT MASK CPI MODDCDA ;IS IT STILL ON? CNZ CARCK ;IF NOT, CONTINUE TESTING IT POP D ;RESTORE D,E JMP SENDW ;ELSE, WAIT FOR XMIT READY. ; ;Xmit status ready, carrier still on - send the data. ; SENDR POP PSW ;GET CHAR OUT MODDATP ;OUTPUT IT RET ;FROM "SEND" ; ;----> WAITNAK: Waits for initial NAK ; ;LL CTYPE ;TYPE THE MSG INX H ;TO NEXT CHAR JMP ILPLP ;LOOP ; ILPRET XTHL ;RESTORE HL RET ;PAST MSG ; EXITLG ; SPECIAL LOG CALLER EXIT IF LOGCAL JMP LOGCALL ENDIF JMP EXIT ; ;----> ERXIT: Exit printing message following call ; ERXIT POP D ;GET MESSAGE MVI C,PRINT ;GET BDOS FNC CALL BDOS ;PRINT MESSAGE ; EXIT LHLD STACK ;GET ORIGINAL STACK SPHL ;RESTORE IT ; IF VOUT ; PUSH PSW ; MVI A,0FFH ;FORCE ECHO-ON. STA ECHOFLG ; POP PSW ; ENDIF ;VOUT ; if setare(MODEM FN.FT S), this ;routine moves the filename from the second FCB ;to the first. ; MOVEFCB LXI H,FCB+16 ;FROM LXI D,FCB ;TO MVI B,16 ;LEN CALL MOVE ;DO THE MOVE XRA A ;GET 0 STA FCBSNO ;ZERO SECTOR # STA FCBEXT ;..AND EXTENT RET ; CTYPE PUSH B ;SAVE.. PUSH D ;..ALL.. PUSH H ;..REGS MOV E,A ;CHAR TO E MVI C,WRCON ;GET BDOS FNC CALL BDOS ;PRIN THE CHR POP H ;RESTORE.. POP D ;..ALL.. POP B ;..REGS RET ;FROM "CTYPE" ; HEXO PUSH PSW ;SAVE FOR RIGHT DIGIT RAR ;RIGHT NEXT "FROM" INX D ;TO NEXT "TO" DCR B ;MORE? JNZ MOVE ;..YES, LOOP RET ;..NO, RETURN ; ;************************************************************************ ;* CRCSUBS (Cyclic Redundancy Code Subroutines) version 1.20 * ;* 8080 Mnemonics * ;* * ;* These subroutines will compute and check a true 16-bit * ;* Cyclic Redundancy Code for a message of arbitrary length. * ;* * ;* The use of this scheme will guarantee detection of all * ;* single and double bitTo ensure no data is sent until the receiving ;program is ready, this routine waits for the ;first timeout-NAK or the letter 'C' for CRC ;from the receiver. If CRC is in effect, then ;Cyclic Redundancy Checks are used instead of ;checksums. ;(E) contains the # of seconds to wait. ; ; If the first character received is a CAN (control-X) ; then the send will be aborted as though it had timed out. ; 04/01/82 BHK ; WAITNAK MVI B,1 ;TIMEOUT DELAY CALL RECV ;DID WE GET.. CPI NAK ;..A NAK? RZ a call restu ; restore old area user & drive ..a 01/06/81 endif ; RET ;--EXIT-- TO CP/M ; if setarea ; ;------> RESTORE THE OLD USER AREA AND DRIVE FROM A RECEIVED FILE ; RESTU lda olddrv ;RESTORE THE OLD DRIVE ;a 01/06/81 mov e,a ;a 01/06/81 call recdrx ;a 01/06/81 lda olduser ;RESTORE THE OLD USER NUMBER ;a 01/06/81 mov e,a ;a 01/06/81 jmp recare ;a 01/06/91 ; ;--------> SET USER AREA TO RECEIVE FILE RECAREA call recdrv ;ok set the drive to its place ;a%   errors, all errors with an odd * ;* number of error bits, all burst errors of length 16 or * ;* less, 99.9969% of all 17-bit error bursts, and 99.9984% * ;* of all possible longer error bursts. (Ref: Computer * ;* Networks, Andrew S. Tanenbaum, Prentiss-Hall, 1981) * ;* * ;* * ;* There are four entry points, which are used as follows: * ;* * ;* CLRCRC - A call to this entry resets the CRC accumulator. * ;* It must be called at the start of each message. * ********************************************************************** ; ; ENTRY CLRCRC,UPDCRC,FINCRC,CHKCRC ; CLRCRC: EQU $ ; Reset CRC Accumulator for a new message. PUSH H LXI H,0 SHLD CRCVAL POP H RET ; UPDCRC: EQU $ ; Update CRC Accumulator using byte in (A). PUSH PSW PUSH B PUSH H MVI B,8 MOV C,A LHLD CRCVAL UPDLOOP:MOV A,C RLC MOV C,A MOV A,L RAL MOV L,A MOV A,H RAL MOV H,A JNC SKIPIT MOV A,H ; The generator is X^16 + X^12 + X^5 + 1 XRI 10H ; as s: (DE) = calculated CRC bytes. * ;* All other registers preserved. * ;* * ;* * ;* CHKCRC - A call to this routine checks the CRC bytes of * ;* a RECEIVED message and returns a code to indicate * ;* whether the message was received correctly. It must * ;* be called after the message AND the two CRC bytes * ;* have been received AND passed thru UPDCRC. * ;* * ;* Entry Parameters: None. * ;* * ;* Exit Conditions: (A) = 0 if message ok. * OR DCH ERRCDE DB 0 ;RECEIVE ERROR CODE ENDIF ; CRCFLG DB 'C' ;SET TO NULL IF CRC USED FIRSTIME DB 1 ;TURNED OFF AFTER FIRST SOH RECEIVED ; ;Following 3 used by disk buffering routines EOFLG DB 0 ;EOF FLAG (1=TRUE) SECPTR DW DBUF SECINBF DB 0 ;# OF SECTORS IN BUFFER DS 60 ;STACK AREA STACK DS 2 ;STACK POINTER ; ;16 sector disk buffer ; DBUF EQU $ ;16 SECTOR DISK BUFFER ; ;BDOS equates ; RDCON EQU 1 WRCON EQU 2 PRINT EQU 9 CONST EQU 11 ;CONSOLE STAT SELDRV EQU 14 ;SELECT DRIVE OPEN  ;* * ;* Entry Parameters: None. * ;* * ;* Exit Conditions: CRC accumulator cleared. * ;* All registers preserved. * ;* * ;* * ;* UPDCRC - A call to this entry updates the CRC accumulator. * ;* It must be called once for each byte in the * ;* message for which the CRC is being calculated. * ;* * ;* Entry Parameters: (A) = a byte to be included * ;* in the CRC calculation. * ;* * ;* Exit Conditions: CRC accumulatorrecommended by CCITT. MOV H,A ; An alternate generator which is often MOV A,L ; used in synchronous transmission protocols XRI 21H ; is X^16 + X^15 + X^2 + 1. This may be MOV L,A ; used by substituting XOR 80H for XOR 10H SKIPIT: DCR B ; and XOR 05H for XOR 21H in the adjacent code. JNZ UPDLOOP SHLD CRCVAL POP H POP B POP PSW RET ; FINCRC: EQU $ ; Finish CRC calc for outbound message. PUSH PSW XRA A CALL UPDCRC CALL UPDCRC PUSH H LHLD CRCVAL MOV D,H MOV E,L POP ;* (A) = -1 if message garbled. * ;* All other registers preserved. * ;* * ;************************************************************************ ;* * ;* Designed & coded by Paul Hansknecht, June 13, 1981 * ;* * ;* * ;* Copyright (c) 1981, Carpenter Associates * ;* Box 451 * ;* Bloomfield Hills, MI 48013 * ;* 313/855-3074 * ;* * ;* This program may be freely reproduced for non-profit use. * ;* * ;**EQU 15 ;0FFH = NOT FOUND CLOSE EQU 16 ; " " SRCHF EQU 17 ; " " SRCHN EQU 18 ; " " ERASEF EQU 19 ;NO RET CODE READ EQU 20 ;0=OK, 1=EOF WRITE EQU 21 ;0=OK, 1=ERR, 2=?, 0FFH=NO DIR SPC MAKE EQU 22 ;0FFH=BAD REN EQU 23 ;0FFH=BAD CURDRV EQU 25 ;GET CURRENT DRIVE STDMA EQU 26 ;SET DMA USER EQU 32 ;SET USER AREA TO RECEIVE FILE BDOS EQU BASE+5 FCB EQU BASE+5CH ;SYSTEM FCB FCBEXT EQU FCB+12 ;FILE EXTENT FCBSNO EQU FCB+32 ;SECTOR # FCB2 EQU BASE+6CH ;SECOND FCB ; B1200 EQU 5 ;BAUD updated. * ;* All registers preserved. * ;* * ;* * ;* FINCRC - A call to this entry finishes the CRC calculation * ;* for a message which is to be TRANSMITTED. It must * ;* be called after the last byte of the message has * ;* been passed thru UPDCRC. It returns the calculated * ;* CRC bytes, which must be transmitted as the final * ;* two bytes of the message (first D, then E). * ;* * ;* Entry Parameters: None. * ;* * ;* Exit Condition H POP PSW RET ; CHKCRC: EQU $ ; Check CRC bytes of received message. PUSH H LHLD CRCVAL MOV A,H ORA L POP H RZ MVI A,0FFh RET ; ; CRCVAL DW 0 ; ; ; ;Temporary storage area ; MAXEXT DB 0 ;HIGHEST EXTENT NO. SEEN IN FILE SIZE CALC. RCNT DW 0 ;RECORD COUNT RCVSNO DB 0 ;SECT # RECEIVED SECTNO DB 0 ;CURRENT SECTOR NUMBER SECCNT DW 0 ;TOTAL SECTOR COUNT ERRCT DB 0 ;ERROR COUNT olduser db 0 ;save the org user number olddrv db 0 ;save the org drive number ; IF PMMI OR H8 &   RATE VALUE FOR 8116 BAUD RATE CHIP ; END baud). [Control-X to cancel.] )|3g}o'\2 y2 ! " Ì* !l " : <2 : O \^! +2 ! " Ua ++ERROR WRITING FILE++ $xGPʮŠĺ7̀ O¼g A x̀ Oĺ͆NG++ 9O ++INCOMPLETELY RECEIVED FILE DELETED++ g \>: : /w !~,yͨ z{ ͂[: <2 a ++CAN'T SEND SECTOR - ABORTING++ $+1 ͆a>͆n> a XMODEM PROGRAM CANCELLED $: <2  ڪ |ġ{0+ \>>>>>>> Transferring Files with XMODEM.COM <<<<<<<< XMODEM provides the remote user with a method of causing the remote system (this one) to begin file transfer in the Ward Christenson protocol. Presently you are in the terminal mode with your modem program. To complC ^^2 !l\n 2|2h_A  J 0+ ~\ + #P g  * ~#n !" O* yO}o|gҝ |g}!o‰ " ̀ ̀ * T]* |>C \?2h>2 \<’a ++FILE NOT FOUND++$\<’: o&T: _)))))))" =!oF+++: ox2 ~2 o2h2|\<a ++OPEN ERROR++ $:]:^$a ++THIS FILE IS NOT FOR DISTRIBUTION, SORRY++ $!g~#O File Open - * ]O (O Hex) Sectors (approximately * :<‹|g}o|g}o"&]O mins, |o&]O secs to send at 1200 baud). [Control-X to cancel.] O secs to send at 300 ete the transfer you must be able to get back to the command mode in your modem program. On most modem7 programs ^E does this, ^O does this on SMODEM programs. I mention this early because if you don't know what your modem program uses....Find Out Now. To Send a File to this System +++++++++++++++++++++++++++++++++++++++++++++ You are in the terminal mode Enter XMODEM R filename.ext XMODEM will display a few lines to let you know it is ready to Receive. Enter ^E or ^O To get !9" 1 O XMODEM ver 5.1A [CRC capable] :^CD:]RZ2 :] SʭRa ++INVALID OPTION ON XMODEM COMMAND++ Must be S for SEND; R or RC for RECEIVE $8CͻP͙͌2 :  û> ^ 8O FILE OPEN - READY TO RECEIVE ͔, ͙"9^ !]~ aa ++NO FILE NAME SPECIFIED++ $ ~?o#ca ++CAN'T USE WILD CARD OPTIONS++ $2  ͆hkʘ7͆ҭ: >: >>C: <2 ژ9O ++UNABLE TO RECEIVE BLOCK - ABORTI'  back to the command mode. Enter S filename.ext Where the filename.ext is the same as you entered for XMODEM. When the file transfer is complete, enter a T to get back into terminal mode. ___________________________________________________________________________ Example: You wish to send a file call MY.LET to this system. You are in the terminal mode. You are using SMODEM. A0>XMODEM R MY.LET The A0> prompt is from this system. XMODEM will sign on then.......... enter ^O to return to the command mode. COMMAND>>S MY.LET Will begin transmission. --------------------------------------------------------------------------- To Receive a File from this System+++++++++++++++++++++++++++++++++++++++++ You are in the terminal mode. Enter XMODEM S filename.ext Again XMODEM will display a brief sign-on message. Enter ^E or ^O To get back into commnad mode Enter R filename.ext Again the filename must be the same as you specified in XMODEM. When the file transfer is complete, enter a T to get back to terminal mode. ___________________________________________________________________________ Example: You wish to receive this help file. You are in terminal mode. You are using MODEM7. A0>XMODEM S XMODEM.DOC XMODEM will sign on Then........ Enter ^E to get into the command mode. COMMAND:R XMODEM.DOC Will begin the transfer .................................Good luck.................................