IMD 1.16: 8/06/2007 14:09:52 ebmmug.017 eastbay micromate users' group kermit-modem program, micromate to a mainframe running unix. disk issued: april 4, 1985 -EBMMUG 017 K40FILESIS CP4KER EXi CP4TYP SM/CP4DEF SM2CP4SYS SM !"#$%&'(CP4SYS SMc)*+,-./01234567CP4LNK SM089:CP4CMD SM!;<=>?@ABCDECP4CPM SM4FGHICP4KER SMJKCP4MIT SMLMNOPQRSTUCP4PKT SMVWXYZ[\]^_`abcdeCP4PKT SMofghijklmnopqrstCP4TT SMuvwxyz{|}CP4UTL SM"~CP4WLD SMCPMNEW OCECP4MIT PDQCOMMER DOC5KERMIT COMn-EBMMUG BAK EBMDIR17TXT-EBMMUG 016-CATALOGBAK-CATALOG  14 Files for Kermit-80 version 4 ================================ Documentation: CPMNEW.DOC 4 8795 ; how to create a runnable Kermit CP4MIT.UPD 11 26733 ; changes between v3.8 and v4.0 of Kermit-80 System-Dependent: CP4TYP.ASM 3 5965 ; selects target system and assembler CP4DEF.ASM 3 6297 ; common definitions (both modules) CP4LNK.ASM 3 6050 ; linkage area description CP4SYS.ASM 25 61698 ; system-dependent code and tables System-Independent: CP4KER.ASM 2 3487 ; header for system-independent module CP4CMD.ASM 9 20569 ; command parser CP4CPM.ASM 3 6627 ; CP/M command support (DIR, ERA) CP4DEF.ASM 3 6297 ; common definitions (both modules) CP4MIT.ASM 8 18799 ; initialization, main loop, some commands CP4PKT.ASM 25 63250 ; KERMIT protocol handler CP4TT.ASM 7 16658 ; transparent communication handler CP4UTL.ASM 9 20647 ; Various utilities and data, and END CP4WLD.ASM 2 3921 ; wildcard handler entation: C! p+q!" * "{  "} *{ ~° ͼ! 6: *{ ~~H ! 6*} ~2 * &*} " Â! 62.* DM -  ̀  ͥ! 6>! B * &  Nͥ: <2  ! r+s+p+q+q! 6: =! ڊ * &* * &*  ʀ >: <2 W >_ogDM!>))덑o|gҳ =¡ DM!>)) = O{ozgi`N#Fogo&og_{_z#W0)덑o|g =o&og~ :1E010000C32201C37601C384214350344D49542E41534D202834292020332D41756737 :1E011E002D3834242100003922F230313431112122CDA3210E19CD05003C3237312AF4 :1E013C0000347CB5CA6401116DFF197CB5C26D012A023411FAFF197CB5C26D01CD3F2A :1E015A003411EB26CDA321C3760111BA23CDA321C3ED0111F023CDA321C3ED0131346B :1E01780031CD0F34AF326E1B326F1B3A3731C640323D22113222CD891B11AC2D216583 :1E01960027CD692121A2014F060009E9C39116C3E701C3F201C3FE01C36F05C34208F1 :1E01B400C33F02C3E503C3EE03C36010C3AD10C3D801C3F018C37F1AC35F15115C228E :1E01D200CDA321C37601CD7B21CDB910C37601CD5434C3EA01CD7B21CD42342AF23010 :1E01F000F9C9CD7B21116527CDA321C376013E03115C00CDEB1BC3CF01CD7B21213F81 :1E020E003136FF2180002248310E13115C00CD0500AF326800326A00327C000E161108 :1E022C005C00CD0500FEFFC27601115823CDA321C3760111372E21F028CD6921215082 :1E024A00024F060009E9C3DF02C32003C3F302C3CF01C3BC02C31703C34203C35103FB :1E026800C38302C38903C3B803C39A03C39202C3FC02C30E03C30503C3600311FF2EE8 :1E02860021CE2ACDD803328B34C37601115C003E10CDEB1BC39D023A5C00B7C2A702C6 :1E02A4003A37313237310E0DCD05003A37313D5F0E0ECD0500C3760111E72E21BA2A82 :1E02C200CD692121CD024F060009E9C3D902C3D302CD7B21C37601CD7B21C37601CD47 :1E02E0007B21111827CDA3210E01CD0500327634C37601CDD203327A34C37601CDD231 :1E02FE0003323831C37601CDD203327934C37601CDD203323931C37601CDD203327B88 :1E031C0034C37601CDD203327C34B7CA31033E030601C335033E060600327E34783201 :1E033A007A34323931C3760111802F21122BCDD803327D34C3760111492F21982BCD04 :1E035800D803327E34C37601119F2F21292BCDD803B7CA8303FE01CA8003113B27CDFF :1E037600A3210E01CD0500328D343A8D34328C34C376013A7534FEFFCA4D05CDD2030C :1E039400327534C376012A6B347CB5CA4D05EB2A6D34CD6921D5CD7B21E1227734EB3C :1E03B200CD5734C376012A6F347CB5CA4D05EB2A7134CD6921D5CD7B21E1CD5A34C333 :1E03D000760111722F21B32BCD692132A832CD7B213AA832C9CD7B21CDF703C37601D4 :1E03EE00CD7B21CDF703C376013A4131B7CA040411742CCDA321CD33043A7534FEFF2C :1E040C00C43F04CD5004CD6E04CD7A04CD8604CD92042A6B347CB5C4C104CDFA04CD4B :1E042A000F05CD1B05CD2705C9118A2CCDA3213A7A34C3400511A02CCDA3213A753458 :1E044800FEFFC24005C34D0511B12CCDA3213A7D3411BD2CB7CAA32111C62CFE01CA08 :1E046600A32111CD2CC3A32111D52CCDA3213A7C34C3400511E02CCDA3213A7B34C334 :1E048400400511EF2CCDA3213A3831C34005112E2DCDA3213A7E3411392DFE06CAA3DC :1E04A20021113E2DFE03CAA32111432DFE0CCAA32111492DFE09CAA321114D2DC3A3EA :1E04C0002111522DCDA3213A7734215B2DFEFFCAF6042A6B34562346042322A83223BF :1E04DE0005C2DD044EB9CAF304232315C2D704215B2DC3F6042AA832EBC3A321110E9D :1E04FC002DCDA3213A8B345F0E02CD050011232DC3A32111FE2CCDA321CD4F21C3A096 :1E051A002111762DCDA3213A3931C34005117C2DCDA321119B2C3A8C34B7CAA3210E41 :1E053800025FCD0500C3A02111972CB7C2A321119B2CC3A32111D924CDA321C37601A5 :1E055600435034504B542E41534D202833292032372D4A756C2D3834241162313E0599 :1E057400CDEB1BC3CF01B7CAA40532AD32EB3624CDAF14CD2D34116231CDA3213E3121 :1E059200325331AF32AC323E52CDFF10C3CF01C3A705CDAF14AF3255312100002257D7 :1E05B00031225931325631325B31CD3334210000CD84213E52325D31CD30342A5731DF :1E05CE00CD84213A5D31FE44C2DF05CD5E07C3C805FE46C2EA05CD9306C3C805FE52F0 :1E05EC00C20306CD2D063A5D31FE46C2C80511BA26CDED14C3C805FE43C21F06111DE6 :1E060A00243A5531B7CA1906AF32553111EE24CDED14C37601FE41C22406112824CD67 :1E062800ED14C376013A5B31FE10FA3E06116D22CDA314C3B6143C325B313E313253C8 :1E06460031CDF611C3BF14FE53C288063A5B31325C31AF325B313AAC32CD02153AAD85 :1E06640032216231CDB30C216231CD720C32AD323E59CDFF10C3B6143A543132533181 :1E0682003E46325D31C9FE45C2BC14CD7E14C3B6143A5B31FE05FAA406118B22CDA3F1 :1E06A00014C3B6143C325B31CDF611C3BF14FE53C2EF063A5C31FE10FAC406116D22F6 :1E06BE00CDA314C3B6143C325C313A56313DE63F473AAC32B8C2BC14CDD214AF325B57 :1E06DC0031216231CD720C32AD323E59CDFF10C3B614C9FE5AC209073A5C31FE05FA08 :1E06FA00050711AA22CDA314C3B614CD2015C9FE46C23607CDF914C2BC14CD0215CDBD :1E071800D20EC3B6143A5B31325C31CD10153E44325D313A5531FE5AC8AF325531C98D :1E073600FE42C25307CDF914C2BC14AF32AD323E59CDFF10C3B6143E43325D31C9FE15 :1E07540045C2B614CD7E14C3B6143A5B31FE05FA6F0711CB22CDA314C3B6143C325BB9 :1E07720031CDF611C3BF14FE44C2CD07CDF914CA99073A5C31FE05FA950711CB22CD87 :1E079000A314C3B614CD2015C9CD02153A5B31325C313AAD32CD4B0DC3B614AF325BCC :1E07AE003132AD324F3A5531B7CAC4074F3E0132AD32793262313E59CDFF10C3B614B3 :1E07CC00C9FE46C2E7073A5C31FE05FAE307118B22CDA314C3B614CD2015C9FE5AC2F0 :1E07EA003708CDF914C2BC14CD02153AAD32FE01C205083A6231FE44CA28082A4831CF :1E0808003A44313DB7FA1608361A23C30B08CDFE21C3B6140E10115C00CD0500AF3217 :1E08260055313A5B31325C31CD10153E46325D31C9FE45C2B614CD7E14C3B6143E02AF :1E084400115C00CDEB1BC37601CD7B21CDC91AD25F08112823CDA314C37601CDAF1420 :1E086200AF325631325B31323C31210000225731225931CD3334210000CD84213E3106 :1E0880003253313E53325D31CD30342A5731CD84213A5D31FE44C29F08CD710AC388F8 :1E089E0008FE46C2AA08CD9C09C38808FE5AC2B508CD680BC38808FE53C2CE08CD088F :1E08BC00093A5D31FE46C2880811AF26CDED14C38808FE42C2D908CD070CC38808FE9C :1E08DA0043C2F108111D243A5531B7CAEB0811EE24CDED14C37601FE41C2FF08112810 :1E08F80024CDED14C37601112824CDED14C376013A5B31FE10FA190911F222CDA314B8 :1E091600C3B6143C325B313E313253313A8B34325431216231CD720C32AD323A573195 :1E09340032AC323E53CDFF10C3B614CDF611C3AD21FE59C27309CDF914C0CD02153AE9 :1E095200AD32216231CDB30C3A5B31325C31AF325B313A54313253313E46325D31CDF0 :1E097000AE21C9FE4EC29109CDD2143A56313CE63F473AAC32B8C0AF325B313E46325A :1E098E005D31C9FE45C2B614CD7E14C3B6143A5B31FE05FAAD0911F222CDA314C3B69E :1E09AC00143C325B31AF325531216231224C31215D00224A3106000E0078FE08C2D620 :1E09CA00093E2E2A4C317723224C310C0478FE0CF2F8092A4A317EE67F23224A31FEEF :1E09E80021FAC5092A4C317723224C310CC3C5097932AD322A4C313E2477CD2D341142 :1E0A06006231CDA3213A563132AC323E46CDFF10C3B614CDF611C3AD21FE59C24F0A19 :1E0A2400CDF914C0CD02153A5B31325C31AF325B31CDC30DC3440A3252313E44325DD0 :1E0A420031C9FEFFC2B6143E5A325D31C9FE4EC2660ACDD2143A56313CE63F473AAC72 :1E0A600032B8C0C3280AFE45C2B614CD7E14C3B6143A5B31FE05FA820A11F222CDA33A :1E0A7E0014C3B6143C325B31216231224C31212332224E3106012A4E317E23224E3163 :1E0A9C004F3A3E31B779C2C60A3A7E34FE0679CAC60A3A3C31B7C2C30A79E680CAC326 :1E0ABA000ACDE0143EFF323C3179E67F2A4C317723224C31043A5231B8F2940A3A5224 :1E0AD8003132AD323A563132AC323E44CDFF10C3B614CDF611C3AD21FE59C2460BCD66 :1E0AF600F914C03AAC32CD02153A5B31325C31AF325B313AAD32FE01C2240B3A623151 :1E0B1400FE5AC21C0B325531FE58C2240B3255313A5531B7CA310B3E5A325D31C9CD60 :1E0B3200C30DC33B0B325231C9FEFFC2B6143E5A325D31C9FE4EC25D0BCDD2143A56EB :1E0B5000313CE63F473AAC32B8C0C3310BFE45C2B614CD7E14C3B6143A5B31FE05FAA1 :1E0B6E00790B11F222CDA314C3B6143C325B313A563132AC32AF32AD323A5531B7CAE3 :1E0B8C00980B3E443262313E0132AD323E5ACDFF10C3B614CDF611C3AD21FE59C2E5AD :1E0BAA000BCDF914C0CD02153A5B31325C31AF325B310E10115C00CD05003A5531FE97 :1E0BC8005ACADF0BCDC91ADADF0BCDAE21AF3255313E46325D31C93E42325D31C9FE76 :1E0BE6004EC2FC0BCDD2143A56313CE63F473AAC32B8C0C3AF0BFE45C2B614CD7E1483 :1E0C0400C3B6143A5B31FE05FA180C11F222CDA314C3B6143C325B313A563132AC325D :1E0C2200AF32AD323E42CDFF10C3B614CDF611C3AD21FE59C2500CCDF914C0CD0215B3 :1E0C40003A5B31325C31AF325B313E43325D31C9FE4EC2670CCDD2143A56313CE63F44 :1E0C5E00473AAC32B8C0C33D0CFE45C2B614CD7E14C3B6143A8034C62077233A82347C :1E0C7C00C62077233A8434C62077233A8634C640E67F77233A8834C62077233A8A3401 :1E0C9A00772336593A7E34FE06CAAA0C3A3D3177233A8B3477233E08C932AB323E0D65 :1E0CB8003287343E233289343E26323D313E313254317EDE20327F343AAB32FE03F846 :1E0CD60023237EDE203283343AAB32FE04F8237EC640E67F3285343AAB32FE05F82318 :1E0CF4007EDE203287343AAB32FE06F8237E3289343AAB32FE07F8233E00323E317E42 :1E0D1200FE4ECA390DFE20CA390DFE59C2310D3A7E34FE06CA390D3EFF323E31C33908 :1E0D30000D323D313EFF323E313AAB32FE08F8237E473A8B34B8C0325431C932A83220 :1E0D4E002162312246313A8A34470E003A3E31B7CA650D3A3D314F21A83235FAA82167 :1E0D6C0021443135F2790DCDFE21C3AD212A46317E232246311E00B9C2950D1E803ABB :1E0D8A00A8323D32A8327E23224631B8C2B70D7E2322463121A8323557E680B35F7AFD :1E0DA800E67FB8CAB70DB9CAB70D7AC640E67FB32A48317723224831C3650D3A89349F :1E0DC6004F3A5331D631473A7F34D6059032A832212332224E3106003AA8323DF2E907 :1E0DE4000D78C3A82132A8323A44313DFAF90D324431C30A0ECDC721C3020EC30A0E03 :1E0E020078B7C2A821C3CF0E2A48317E2322483157E6805FCA3A0E3A3E31B7CA3A0EF9 :1E0E20003AA832FE02FAC00E3D32A8322A4E313A3D317723224E31041E007AE67F57AB :1E0E3E00FE20FA6C0EFE7FCA6C0E3A3E31B7CA560E3A3D31BACA5B0E7AB9C2B30E2149 :1E0E5C00A832352A4E317123224E31047AC3B30EB3FE1AC29C0E3A7D34FE01CA8B0E05 :1E0E7A00FE02CA9A0E2A48313A443157157AF2930EAF32443178C3A8217E23FE1ACA40 :1E0E9800860E3E1A32A93221A832352A4E317123224E31043AA932C640E67F2A4E3108 :1E0EB600B37723224E3104C3DE0D2A48312B2248312144313478C3A8213EFFC92162BE :1E0ED40031224C31215D00224A31AF32A83232A932325C00062070233CFE0CFAEA0ECE :1E0EF2002A4C317EFE61FAFD0EE65F23FE2EC21A0F224C31216500224A313AA83232D2 :1E0F1000A9323E0932A832C3490FB7CA700F224C312A4A317723224A313AA8323C327D :1E0F2E00A832FE08FAF20E32A9322A4C317E23224C31B7CA700FFE2EC2350F2A4C31FE :1E0F4C007EFE61FA540FE65FB7CA700F23224C312A4A317723224A313AA8323C32A840 :1E0F6A0032FE0CFA490F2A4C313624CD2D34116231CDA3213A7B34B7CA2F100E0F11A0 :1E0F88005C00CD0500FEFFCA2F10113024CDA3143AA932B7C2A50F3AA83232A93206C5 :1E0FA60000503CFE09C2B10F06FF3D5F215C00193626C5D5215C000E0C7EE67F7723D7 :1E0FC4000DC2BF0F0E0F115C00CD0500D1C1FEFFCAFC0F78B7CAE50F1D7BB7CAF50FA8 :1E0FE200C3B20F1C7BFE09FAB20F3AA9325F06FFC3B20F114123CDA321C90E08118899 :1E10000032215D0006007E23FE20CA131012130DC2061078B7C226103E2E121306FFA9 :1E101E000E03216500C306103E2412118832CDA3210E13115C00CD0500AF3268003299 :1E103C006A00327C003E803244312180002248310E16115C00CD0500FEFFC2A82111E1 :1E105A00E522CDA314C9CD7B21AF325B313E313253313A5B31FE05FA7D10116523CD73 :1E107800A321C376013C325B31AF32AC323E0132AD3221623136463E47CDFF10C3748B :1E10960010CDF611C36C10FE59CA7601FE45C26C10CD8914C37601CD7B21CDB910C39A :1E10B4007601C37601AF325B313E313253313A5B31FE05FAD110119923CDA321C93CD4 :1E10D200325B31AF32AC323E0132AD32216231364C3E47CDFF10C3CA10CDF611C3C2A6 :1E10F00010FE59CAA821FE45C2C210CD8914C932AE32215E313E0177233A5331D6317E :1E110E00473AAD32C6238077230100004F3AAC32C6207723814F3E0088473AAE32770A :1E112C0023814F3E0088473AAD32B7CA49113D32AD327E23814F3E008847C333113AA4 :1E114A005331FE32CA7A11D2631179E6C0070781E63FC6207723C391113600E5215FE5 :1E11680031CD0814E14B427A07070707E60FC620772378E60F070747790707E603B0F4 :1E118600C620772379E63FC62077233A87347723AF77CD06343A833432A8323AA832E0 :1E11A4003DB7FAB91132A8323A8534CD0F215FCD0934C3A1113A7934B7CACF11CD0F77 :1E11C20034CD3C34215F31CD3915CD0634215E317EB7CAF011CD0F215FCD09343A8CEF :1E11E00034BEC2EC11CD0F215FCD093423C3D211CD0F34C3A821CD1D13C3AD21CD9981 :1E11FE0013C3F611FE01C2FC11CD9913C3AD21FE01CA0712325F314F3A5331D631471F :1E121C0079D6239032AD320600CD9913C3AD21FE01CA071232AC32326031814F3E00CE :1E123A0088473AAC32D62032AC32CD9913C3AD21FE01CA071232A832326131814F3EDF :1E1258000088473AAD3232A932216231224C313AA932D601FA8E1232A932CD9913C361 :1E127600AD21FE01CA07122A4C317723224C31814F3E008847C36712CD9913C3AD21A7 :1E129400FE01CA0712D62032AA323A5331FE32CAE912D2BD1279E6C0070781E63F47E8 :1E12B2003AAA32B8CA1213CDD214C92A4C313600215F31CD08144B427A07070707E665 :1E12D0000F573AAA32BAC2B912CD9913C3AD21FE01CA0712D62032AA3278E60F0707D2 :1E12EE0047790707E603B0473AAA32B8C2B912CD9913C3AD21FE01CA0712D620477937 :1E130C00E63FB8C2B9122A4C3136003AA832C3A82121BC31225031CDA613C3AD21FE16 :1E132A0001C22313C34213CDA613C3AD21FE01C2421321BC312250312A50317723224F :1E13480050314711DFCD19DA1D133A8834B8C231133A7C34B7CA73133A5D31FE53CA57 :1E1366007313CDA613C37313FE11C268132A50312B36003A7934B7CA901323CD0F347E :1E138400CD393421BD31CD3915CD063421BC31225031C3A8212A50317E23225031B7FD :1E13A200C2A821C9E5C52A7334223A31CD0634CD0C34B7CAC913473A7E34FE0678CAE7 :1E13C000C413E67FC1E1C3A821CD0F34CD1534B7CAEF13FE0DCAEC13FE1ACAE713FE4E :1E13DE0003CA7601FE18C2EF13C640325531C1E1C93A3931B7CAAE132A3A312B223AA8 :1E13FC00317CB5C2AE13CDD214C1E1C9E5C51100007EB7CA3B14E5AB5FE60F4F06008E :1E141A00215E140909E57B0F0F0FE61E4F213E14097EAA2356E1AE5F237EAA57E1237E :1E143800C30D14C1E1C900008110022183310442855206638773088489940AA58BB5C7 :1E1456000CC68DD60EE78FF70000891112239B322446AD573665BF74488CC19D5AAFB5 :1E147400D3BE6CCAE5DB7EE9F7F8CD2A343E41325D31C38F14114122CDA3213AAD328F :1E1492004F0600216231093E2477116231CDA321C9D5CD2A34CD1B34D1CDA321C911FB :1E14B0002122CD5D34C93E41325D31C9CDD2143A563132AC32AF32AD323E4ECDFF1000 :1E14CE00C3B614C9CD33342A593123225931CD8421C9C5D5E511C726CDA314E1D1C144 :1E14EC00C9D5CD3634D1CDA321CD2734C93A5631473AAC32B8C93CE63F3256312A577E :1E150A003123225731C9AF325B3132AD323E59CDFF10C3B614C93C325C313A56313DBC :1E152800E63F473AAC32B8C2BC14CDD214CD1015C97EB7C8E55FCD1234E123C3391500 :1E15460043503454542E41534D20202833292032372D4A756C2D3834243E03115C00F9 :1E156400CDEB1BC37601CD7B21CDAE21FEFFC27E15112823CDA321C37601114E25CD8D :1E158200A321CD4F21112626CDA321CD4F21115226CDA3213E01324131AF324231CD01 :1E15A000BB160E0BCD0500B7CA9F153A3631B7C27516AF4F3258301165302A48313A5C :1E15BE0044314705F2D215CDC721C3FE152A48313A4431477E23E67FCAC115FE0DCAD6 :1E15DC00F515FE1ACAFB15FE0ACAFE1512133A5830B7C2F2150CC3C115325830C3C1C6 :1E15FA001532363122483178324431793245313A453132593021653022EA30CDBB164F :1E1618003A4231B7C215163A59303DFA5D16325930CD06342AEA307E2322EA30CD0F37 :1E163600215FCD09343A8C34BEC24916CD0F215FCD09343A7A34B7CA15167BE67F5FFA :1E165400CD0F34CD1234C31516AF32A832CDBB16CDD717C37E163AA832FE0DCA9F155F :1E167200C36116CD8416116E26C39716CD8416C376010E10115C00CD0500AF32413153 :1E169000C9CD7B21115C24CDA321CD4F21118024CDA321CD4F21119524CDA321CD45BB :1E16AE0034CDBB16CDD717C37601C3AF16CD0634CD0C34B7C2C916CD0F34C9E67FCA5B :1E16CC00BB16FE7FCABB16FE11CA1F17FE13CA20175F3A7534FE01C201173A4031B779 :1E16EA00CAF316CD5E17C3BB167BFE1BC201173E01324031C3BB16CD5134B7CABB16B1 :1E1708003A3F31B7C42617CD0F343A3831B7C41834CD1234C3BB16AF324231C3BB1658 :1E1726002A483173232248317DB7C0D53E13CD0F215FCD09340E15115C00CD0500B738 :1E174400CA4D1711E522CDA3213E11CD0F215FCD0934218000224831D1C9FE01C2B3B1 :1E176200177BFE59C26F173E02324031C9FE5ACA9517FE41FA9017FE4CF29017D641E4 :1E17800007072A69345F160019EBCD0F34CDA321AF324031C93E1BCD0F215FCD093482 :1E179E003E2FCD0F215FCD09343E4BCD0F215FCD0934C39017FE02C2C4177BD61F32C2 :1E17BC0043313E03324031C9AF3240317BD61F4F3A433147CD0F34CD6034C9CD153498 :1E17DA00E67FCAA8215F32A8323A7634BBCA0918CD06347BCD0F215FCD0934CD0F340C :1E17F8003A7A34B7CAA8217BE67F5FCD1234C3A821CD1534B7CA091847FE03CA1D18C4 :1E181600E65FFE43C24B1811AB24CDA321CD48343A3F31B7C8AF323F31114324CDA3ED :1E183400212A4831361A0E15115C00CD05000E10115C00CD0500C9FE53C25618CDF7B5 :1E18520003C3A821FE12CA6018FE52C26B183A4131B7CA6B18C1C3091678FE3FC2999F :1E187000183A4131B7CA7E1811BC2BCDA32111D92BCDA321CD4B34113C2CCDA321CD2D :1E188E004F21114E2CCDA321C3091878FE30C2B018AFCD0F215FCD0634CD0934CD0FA4 :1E18AC0034C3A8213A7634B8C2C81878CD0F215FCD0634CD0934CD0F34C3A82178CD5A :1E18CA004E34C3A8211E07CD1234C3A82143503443504D2E41534D202833292020385C :1E18E8002D4A756C2D383424115C003E10CDEB1BC3FE18C316193A5C00FE20C20A19DB :1E190600AF325C00215D00060B363F2305C20F193A5C00B7C220193A3731C640321539 :1E19240025CDA02111FB24CDA3213E04329234CD651ACDC91AD23F19C3B9190E0BCD56 :1E1942000500B7CA50190E01CD0500C3B919215D000608CD91193E2ECD84190603CD73 :1E1960009119CDFD1921923435F5C47419F1CC9D19C33619CD82193E3ACD8419C38266 :1E197E0019CD82193E20C5D5E55F0E02CD0500E1D1C1C97EE67FCD84192305C291198F :1E199C00C9C5D5E5CDA021E1D1C13604C9CDA0213A37313D5F0E0ECD0500C37601AF3E :1E19BA00326E1B326F1B3A5C00B7CACE193D5F0E0ECD0500CD6334E5111A25CDA321E6 :1E19D8003A5C00B7C2E5190E19CD05003CC640322525112525CDA321E1CD8421112CB1 :1E19F60025CDA321C3A9190E23115C00CD05003A7D000100006FE607CA141A0101001A :1E1A1400C50603AF3A7E001F327E003A7D001F327D0005C2171A6F3A7E0067C1093AA1 :1E1A320090340F0F0FE61F4F092FA56FE501F6FF09DA4C1ACD7F19C3581AE1E5019CE4 :1E1A5000FF09DA581ACD8219CD8219E1CD84213E6BCD8419C90E1FCD050023237E3230 :1E1A6E009134237E32903423235E2356EB228E34C93E02115C00CDEB1BC37601115C22 :1E1A8C00000E11CD05003CC29F1A112823CDA321C37601115C000E13CD0500113B259C :1E1AAA00CDA321C37601435034574C442E41534D202833292032372D4A756C2D383478 :1E1AC80024B7C5D5E50E1A118000CD0500AF3268003A6E1BB7C2FA1A326F1B215C0049 :1E1AE60011621B010C00CD66340E11115C00CD0500C3171B3D326F1B21621B115C0089 :1E1B0400010C00CD66340E11115C00CD05000E12CD0500F53A6F1BB7CA271B3D326FA5 :1E1B22001BF1C3121BF1B7FA481BCD4C1B3A621B325C003A6E1B3C326E1B3E00326899 :1E1B400000327D00E1D1C1C937C3441B87878787874F060021800009115C00010C0027 :041B5E00CD6634C953 :1E1B6E000000435034434D442E41534D202833292020382D4A756C2D383424E1E52296 :1E1B8C005D3021000039225B30EB225F30EB21653022EA3022EC30AF325830325930CC :1E1BAA003EFF325A30CDA021C3EE202A5B30F921653022EC303EFF325A302A5D30E98A :1E1BC8002A5B30F921653022EA3022EC30AF3258303259303EFF325A30CDA021CDEEBB :1E1BE600202A5D30E9325730CD5420FE04CA691CFE01CAC41CFE02CA141EFE10CA1445 :1E1C04001EFE03CA121EFE05CA161C11BA2FCDA321C9EB2261300600CDFB1FB7F25DC5 :1E1C22001CE67FFE1BC2461C0E021E07CD0500AF3258302AEA302B22EA3022EC30216C :1E1C4000593035C31C1CFE3FCA581CFE0CCC2434782A6130EBC3A82121583036000497 :1E1C5E002A61307723226130C31C1CCDFB1FB7F0E67FFE1BC2911C0E021E07CD0500E3 :1E1C7C00AF3258302AEA302B22EA3022EC3021593035C3691CFE3FC2BC1C113930CDB3 :1E1C9A00A321CDA021CDEE202AEC303E24772AEA302B22EA30116530CDA321AF3258C5 :1E1CB80030C3B51BFE0CCC2434C3A821226330EB226130462322EE302AEC3022F0300D :1E1CD60078B7C82AEE305E231D7BFEFFFABE1DCDFB1FB7F2AC1DE67FFE3FC21E1DAF1F :1E1CF400325830215930352A6330EBCDA321CDA021CDEE202AEC303E24772AEA302B09 :1E1D120022EA30116530CDA321C3B51BFE1BC28D1DAF325830D5C5E5CDD91DC34C1D51 :1E1D30000E021E07CD05002AEA302B22EA3022EC3021593035E1C1D11CC3DE1C2AEA66 :1E1D4E00302BEBE1E57EFE24CA681D23EB7723EB3A59303C325930C3531D3A59303CFD :1E1D6C00325930EB3E20772322EA3022EC30E1E5EBCDA3210E021E20CD0500E1C1D16C :1E1D8A00C3A01DE5D5CDD91DC39E1D11E02FCDA321C3C81BD1E11C160019235E235672 :1E1DA8007BC3A821FE61FAB81DFE7BF2B81DE65F5623BACADE1C16007BB7F2C71D1638 :1E1DC600FF191103001922EE30052AF03022EC30C3D61C05F81C4B7BB7C81600191E8D :1E1DE40003194623EB2AEE307E914FB8CAF41DF02AF0300DFAA821EB4623EB7E23FE50 :1E1E020061FA0D1EFE7BF20D1EE65FB8C0C3F71D3E0032E930EB22E5301E00360023F0 :1E1E200022E730AF3620233CFE0CFA241ECDFB1FB7F2321FE67FFE3FC2511E21583064 :1E1E3E0036002AEA302322EA302AEC302322EC30C3B11FFE1BC2251FAF3258302AEAD7 :1E1E5C00302B22EA3022EC30215930357B32A832FE09FA721E3D2AE730FE0BF2811E84 :1E1E7A00363F233CC3751E0E112AE530EBCD0500FEFFCA1B1F21CC32CDD41F21DC32F6 :1E1E9800CDD41F0E122AE530EBCD0500FEFFCAAF1E21DC32CDD41F11CC3221DC323A55 :1E1EB600A832FE09FABE1E3D0E00B9CACA1E13230CC3C01E79FE0BCAF61EFE08C2E2B4 :1E1ED4001E3AA832FE09CAE21E3E2ECDEC1F1A134623B8C2F61E0CFE20CACA1ECDECF0 :1E1EF2001FC3CA1E7932A8323E24CDEC1F2AEC30EB0E09CD05002AEA302B22EA302163 :1E1F10005930353AA832FE0BCAB51B0E021E07CD0500C3B51B7BB7CABD1FFE0DF2BD12 :1E1F2E001FC3A821FE2EC2531F1C7BFE01CABD1FFE0AF2BD1F0E0906002AE5300922F1 :1E1F4C00E7301E09C32D1EFE3AC2701F1C7BFE02C2BD1F2AE7302B7ED64022E7302B09 :1E1F6A00771E00C32D1EFE2AC2A01F3AE930FE00CACE1F7BFE08CABD1FF28B1F060834 :1E1F8800C38D1F060C2AE7303E3F772322E7301C7BB8FA8D1FC32D1EFE30FABD1FFE24 :1E1FA6007BF2BD1FFE41FAB11FE65F2AE730772322E7301CC32D1E3A5730FE10CAAD02 :1E1FC4002111ED2F0E09CD0500C9111030C3C81FF51180000707070707833C5F060B2C :1E1FE2001A13772305C2E21FF1C9E52AEA30772322EA3021593034E1C9E5C53A5830A5 :1E200000B7CC54202AEC307E2322EC30FE20CA1620FE09C229203A5A30B7C2FD1F3EDF :1E201E00FF325A303E20C1E1C35120F5AF325A30F1C1E1FE1BCA5120FE3FCA4820FE01 :1E203C000DCA4820FE0ACA4820FE0CC0E52AEC302B22EC30E1F680C9F5D5E53A58301E :1E205A00B7C2EA20215930340E01CD05002AEA30772322EA30FE15CA7920FE18C28D31 :1E20780020CD1B34CDEE2021653022EA302159303600C3B51BFE08CA9A20FE7FC2BE47 :1E20960020CD21343A59303D3DB7F2AD200E021E07CD0500C37920325930CD1E342AD0 :1E20B400EA302B2B22EA30C3B51BFE3FCAE220FE1BCAE220FE0DCADA20FE0ACADA2046 :1E20D200FE0CC25E20CD24343A5930FE01CAC81B3EFF325830C3EA20E1D1F1C92A5F59 :1E20F00030EBCDA321C943503455544C2E41534D202832292020332D4175672D383499 :1E210E0024E5C5217E344E0600211C2109E9C32E21C33821C32B21C33D21C34721C322 :1E212C004C21E67FEA4C21F680C34C21F680C34C21E67FE24C21F680C34C21E67FC39E :1E214A004C21C1E1C93A7634FE20F2622111D024CDA3213A7634F6400E025FCD050037 :1E216800C93E01CDEB1BC37221C9114422CDA321C376013E04CDEB1BC3CF01C901F6B5 :1E218600FF11FFFF0913DA8A21E5EB7CB5C48721E17DC63A5F0E02C305001141220E08 :1E21A40009C30500E1232323E9C9AF324431323631326800326A00327C000E0F115CF3 :1E21C20000CD0500C93A3631B7CAD1210600C0C5D5E5214431367F2180002248310E76 :1E21E00014115C00CD0500B7CAF821AF3244313EFF323631E1D1C1C9E1D1C1C3A8218D :1E21FE00C50E15115C00CD0500C1B7CA132211E522CDA314C92180002248313E7F3295 :1E221C004431C3A8214B65726D69742D38302076342E303220244B65726D69742D3833 :1E223A00302020783A3E240D0A240D0A3F556E7265636F676E697A656420636F6D6DB8 :1E225800616E64240D0A3F4E6F7420636F6E6669726D6564243F556E61626C65207465 :1E2276006F207265636569766520696E6974696174650D0A243F556E61626C652074FC :1E2294006F20726563656976652066696C65206E616D650D0A243F556E61626C652048 :1E22B200746F207265636569766520656E64206F662066696C650D0A243F556E61621C :1E22D0006C6520746F207265636569766520646174610D0A243F4469736B2066756CF3 :1E22EE006C0D0A243F556E61626C6520746F207265636569766520616E2061636B6EE3 :1E230C006F776C656467656D656E742066726F6D2074686520686F73740D0A240D0AB3 :1E232A003F556E61626C6520746F2066696E642066696C650D0A243F556E61626C65AA :1E23480020746F2072656E616D652066696C65240D0A3F4469736B2066756C6C240D13 :1E2366000A3F556E61626C6520746F2074656C6C20686F7374207468617420746865D5 :1E2384002073657373696F6E2069732066696E6973686564240D0A3F556E61626C65E0 :1E23A20020746F2074656C6C20686F737420746F206C6F676F7574240D0A3F4B657212 :1E23C0006D697420686173206E6F74206265656E20636F6E6669677572656420666FF3 :1E23DE00722061207461726765742073797374656D240D0A3F436F6E73697374656E52 :1E23FC00637920636865636B206F6E20636F6E66696775726174696F6E206661696C78 :1E241A0065642407436F6D706C6574656424074661696C6564242552656E616D696E90 :1E243800672066696C6520746F20240D0A5B436C6F73696E6720746865206C6F6720F4 :1E24560066696C655D240D0A5B436F6E6E656374656420746F2072656D6F746520680B :1E2474006F73742E20205479706520244320746F2072657475726E3B0D0A20747970CB :1E2492006520243F20666F7220636F6D6D616E64206C6973745D0D0A240D0A5B436F46 :1E24B0006E6E656374696F6E20636C6F7365642C206261636B206174206D6963726F0A :1E24CE005D24436F6E74726F6C2D2420284E6F7420696D706C656D656E746564290DDA :1E24EC000A2407496E746572727570746564240909202020204469726563746F72799C :1E250A0020666F7220647269766520783A0D0A240D0A090944726976652024202068F6 :1E252800617320244B20627974657320667265650D0A240D0A46696C6528732920650E :1E2546007261736564240D0A0D0A5B5472616E736D697474696E672066696C65207463 :1E2564006F20686F73743A0D0A20312E205479706520616E79206368617261637465B7 :1E2582007220746F2073656E642061206C696E652E0D0A20322E205479706520524575 :1E25A0005455524E20746F207465726D696E61746520746865206C696E6520616E646C :1E25BE0020746F2067657420746865206E657874206C696E652028676F206261636BC5 :1E25DC0020746F20312E290D0A2020202028596F75206D61792073656E64206F74689E :1E25FA0065722063686172616374657273206265666F72652052455455524E2E292C96 :1E2618000D0A2020206F72207479706520245220746F2073656E6420746865207361B2 :1E2636006D65206C696E6520616761696E2C0D0A2020206F72207479706520244320BF :1E265400746F2061626F7274207472616E736D697373696F6E2E5D0D0A240D0A5B5477 :1E26720072616E736D697373696F6E20646F6E652E20436F6E6E6563746564206E6FF0 :1E269000726D616C6C7920746F2072656D6F746520686F73742C0D0A207479706520C9 :1E26AE002453656E64696E672E2E2E24526563656976696E672E2E2E24075761726E8B :1E26CC00696E673A20656967687468206269742063616E6E6F742062652073656E741C :1E26EA00240D0A466F722068656C702C2074797065203F20617420616E7920706F6975 :1E2708006E7420696E206120636F6D6D616E64240D0A5479706520746865206E6577B2 :1E27260020657363617065206368617261637465723A2020240D0A54797065207468E4 :1E27440065206E65772054414320696E74657263657074206368617261637465723ABB :1E2762002020240D0A42594520746F20686F737420284C4F474F55542920616E64205F :1E2780006578697420746F2043502F4D0D0A434F4E4E45435420746F20686F7374202D :1E279E006F6E2073656C656374656420706F72740D0A45524120612043502F4D2066CD :1E27BC00696C650D0A4558495420746F2043502F4D0D0A46494E4953482072756E6E87 :1E27DA00696E67204B65726D6974206F6E2074686520686F73740D0A48454C50206219 :1E27F8007920676976696E672074686973206D6573736167650D0A444952206F6620BE :1E28160063757272656E742075736564204D6963726F2D6469736B0D0A4C4F47207451 :1E2834006865207465726D696E616C2073657373696F6E20746F20612066696C650DC8 :1E2852000A4C4F474F55542074686520686F73740D0A524543454956452066696C656B :1E2870002066726F6D20686F73740D0A53454E442066696C6520746F20686F73740DA9 :1E288E000A534554206120706172616D657465720D0A53484F572074686520706172B8 :1E28AC00616D65746572730D0A535441545553206F66204B65726D69740D0A545241A3 :1E28CA004E534D49542066696C6520746F20686F73742028696E20636F6E6E6563749B :1E28E80020737461746529240D0A42417564202872617465290D0A424C6F636B2D6342 :1E2906006865636B2D747970652028666F72206572726F7220646574656374696F6E71 :1E292400290D0A444542756720286D65737361676573204F4E202F204F4646290D0AC7 :1E29420044454661756C742D6469736B2028746F207265636569766520646174612909 :1E2960000D0A457363617065202863686172616374657220647572696E6720434F4E53 :1E297E004E454354290D0A46696C652D6D6F64652028666F72206F7574676F696E6764 :1E299C002066696C6573290D0A49626D202870617269747920616E64207475726E2055 :1E29BA0061726F756E642068616E646C696E67290D0A4C6F63616C2D6563686F2028D2 :1E29D80068616C662D6475706C6578290D0A5041726974792028666F7220636F6D6D93 :1E29F600756E69636174696F6E206C696E65290D0A504F72742028746F20636F6D6D75 :1E2A1400756E6963617465206F6E290D0A5052696E74657220636F70792028204F4EDA :1E2A3200202F204F464620290D0A54414320496E7465726365707420436861726163D4 :1E2A500074657220544143747261702028204F4E202F204F4666202F204368617261B1 :1E2A6E0063746572290D0A54496D65722028204F4E202F204F466620290D0A567435AD :1E2A8C00322D656D756C6174696F6E0D0A5761726E696E672028666F722066696C65C3 :1E2AAA006E616D6520636F6E666C6963747329240D0A5041442D434841520D0A50415C :1E2AC8004444494E47240D0A312D4348415241435445522D434845434B53554D0D0ACD :1E2AE600322D4348415241435445522D434845434B53554D0D0A332D4348415241434D :1E2B04005445522D4352432D4343495454240D0A41534349490942494E415259094460 :1E2B2200454641554C54240D0A4F4E20746F20656E61626C65205441432074726170A3 :1E2B40000D0A4F464620746F2064697361626C652054414320747261700D0A434841DC :1E2B5E0052414354455220746F20656E61626C6520544143207472617020616E6420CC :1E2B7C007370656369667920696E7465726365707420636861726163746572240D0A52 :1E2B9A004556454E094D41524B094E4F4E45094F4444095350414345240D0A4F464617 :1E2BB800094F4E240D0A522053656E64207468652073616D65206C696E6520616761EA :1E2BD600696E240D0A3F202054686973206D6573736167650D0A432020436C6F736523 :1E2BF4002074686520636F6E6E656374696F6E0D0A302020287A65726F292054726133 :1E2C12006E736D69742061204E554C4C0D0A532020537461747573206F662074686519 :1E2C300020636F6E6E656374696F6E240D0A547970696E6720616E6F7468657220242B :1E2C4E002077696C6C2073656E6420697420746F2074686520686F73740D0A0D0A4316 :1E2C6C006F6D6D616E643E240D0A5472616E736D697474696E6720612066696C6524EC :1E2C8A000D0A4C6F63616C206563686F24206F6E24206F6666240D0A565435322065FA :1E2CA8006D756C6174696F6E240D0A46696C65204D6F6465242064656661756C7424F8 :1E2CC600204153434949242062696E617279240D0A49424D20666C6167240D0A4669E7 :1E2CE4006C65207761726E696E67240D0A5072696E74657220636F7079240D0A4573FE :1E2D02006361706520636861723A20240D0A426C6F636B20636865636B2074797065DC :1E2D20003A20242D636861726163746572240D0A5061726974793A20246E6F6E652437 :1E2D3E006D61726B247370616365246F6464246576656E240D0A537065656420246996 :1E2D5C007320696E64657465726D696E61746520286E6F7420534554292454696D65DC :1E2D7A0072240D0A43757272656E742054414354726170205374617475732F496E741E :1E2D9800657263657074204368617261637465723A20202410034259452421210743AC :1E2DB6004F4E4E45435424000003444952242424034552412427270445584954240314 :1E2DD400030646494E495348241B1B03474554240C0C0448454C50240606034C4F475C :1E2DF200240909064C4F474F5554241E1E0752454345495645240C0C0453454E4424B5 :1E2E10000F0F035345542412120453484F5724151506535441545553241818085452D0 :1E2E2E00414E534D4954242A2A0F044241554424212110424C4F434B2D434845434BA7 :1E2E4C002D54595045241818054445425547242D2D0C44454641554C542D4449534B52 :1E2E6A00242424064553434150452400000946494C452D4D4F44452412120349424D65 :1E2E88002403030A4C4F43414C2D4543484F2406060650415249545924151504504F41 :1E2EA6005254241E1E075052494E54455224272707544143545241502430300554492F :1E2EC4004D4552242A2A0E565435322D454D554C4154494F4E241B1B075741524E49B8 :1E2EE2004E47240F0F02085041442D434841522400000750414444494E472403030382 :1E2F000014312D4348415241435445522D434845434B53554D24313114322D4348416F :1E2F1E005241435445522D434845434B53554D24323215332D434841524143544552CA :1E2F3C002D4352432D434349545424333305044556454E240000044D41524B24030390 :1E2F5A00044E4F4E45240606034F4444240909055350414345240C0C02034F46462434 :1E2F78000000024F4E240101030541534349492401010642494E4152592402020744A1 :1E2F9600454641554C542400000309434841524143544552240202034F464624000075 :1E2FB400024F4E2401010D0A3F50726F6772616D206572726F723A2020496E76616C4E :1E2FD200696420434F4D4E442063616C6C240D0A3F416D626967756F7573240D0A3F27 :1E2FF000496C6C6567616C2043502F4D2066696C652073706563696669636174696F07 :1E300E006E240D0A3F222A22206E6F7420616C6C6F77656420696E2066696C6520738B :1E302C00706563696669636174696F6E2420436F6E6669726D20776974682063617254 :0D304A0072696167652072657475726E248D :0C31370000000000000026000000000066 :023221000D247A :1E340000000000000000C30000C30000C30000C30000C30000C30000C30000C3000096 :1E341E00C30000C30000C30000C30000C30000C30000C30000C30000C30000C30000F2 :1E343C00C30000C30000C30000C30000C30000C30000C30000C30000C30000C30000D4 :0F345A00C30000C30000C30000C30000C3000094 :00000001 ! p+q!" * "{  "} *{ ~° ͼ! 6: *{ ~~H ! 6*} ~2 * &*} " Â! 62.* DM -  ̀  ͥ! 6>! B * &  Nͥ: <2  ! r+s+p+q+q! 6: =! ڊ * &* * &*  ʀ >: <2 W >_ogDM!>))덑o|gҳ =¡ DM!>)) = O{ozgi`N#Fogo&og_{_z#W0)덑o|g =o&og~; CP4TYP.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This is the header file for building the system-dependent overlay ; for KERMIT. It contains the definitions used to select the target ; system, and collects (via INCLUDE or LINK directives) the remaining ; code. If the target system is one of the supported systems ; described below, then this is the only file that needs to be ; edited. ; ; revision history: ; edit 3: July 27, 1984 (CJC) ; Shuffle files around for easier assembly by both M80 and LASM. ; ; edit 2: June 4, 1984 [Toad Hall] ; Added Morrow Decision I (the big S100 bus sucker, not the ; little single motherboard one); added Toad Hall TACTrap to deal ; with those working through a TAC and its intercept character. ; ; edit 1: May, 1984 (CJC) ; extracted from CPMBASE.M80 version 3.9; modifications are described ; in the accompanying .UPD file. ; FALSE EQU 0 TRUE EQU NOT FALSE ; ; Assembler type. Define the appropriate one TRUE, the rest FALSE. (We can't ; use ASM, because it cannot handle multiple input files) mac80 EQU TRUE ; For assembly via MAC80 cross-assembler. m80 EQU FALSE ; For assembly via Microsoft's M80. lasm EQU FALSE ; For assembly via LASM, a public-domain ; assembler. ; ; Address at which the overlay should be loaded. This will not ; change often (no more than once per version of KERMIT); it should ; be updated when a new version of KERMIT is released. ovladr EQU 3400H ; value for KERMIT v4.00 ;Which CP/M system hardware are we building KERMIT-80 for? ;One of the following should be TRUE, the rest FALSE: ; ;We have basically three "classes" of systems: ;Systems supporting the IO-redirection via I/O-Byte robin EQU FALSE ;DEC VT180 = Generic + VT100 screen control gener EQU FALSE ;"Generic" Kermit-80, CP/M calls only. ; (terminal required) dmII EQU FALSE ;"Generic" KERMIT-80 for DECMATE II. mikko EQU FALSE ;"Generic" KERMIT-80 for MikroMikko IF robin OR dmII OR gener OR mikko iobyt EQU TRUE ;Short conditional for above inout EQU FALSE ENDIF;robin OR dmII OR gener ;.. and Systems supporting direct IN / OUT handling of ports brain EQU FALSE ;For Intertec SuperBrain. vector EQU FALSE ;For Vector Graphics. heath EQU FALSE ;For Heath/Zenith H89. z100 EQU FALSE ;For Z-100 under CP/M-85. trs80lb EQU FALSE ;For Lifeboat 2.25C CP/M Display trs80pt EQU FALSE ;For Pickles + Trout CP/M Display telcon EQU FALSE ;For TELCON Zorba portable kpII EQU FALSE ;Kaypro-II bbII EQU FALSE ;BigBoard II (terminal required) mmdI EQU FALSE ;Morrow Micro Decision I (terminal required) mdI EQU FALSE ;Morrow Decision I (the big sucker) ; (terminal required) [Toad Hall] trs80 EQU trs80lb OR trs80pt ; if either, flag TRS-80 system. IF brain OR vector OR heath OR z100 OR trs80 OR telcon OR kpII inout EQU TRUE ;Short conditional for above iobyt EQU FALSE ENDIF;brain OR vector OR heath OR z100 OR trs80 OR telcon OR kpII IF bbII OR mmdI OR mdI ;running out of room [Toad Hall] inout EQU TRUE ;Short conditional for above iobyt EQU FALSE ENDIF;bbII OR mmdI OR mdI [Toad Hall] ;.. and Systems doing neither... osi EQU FALSE ;For Ohio Scientific. osbrn1 EQU FALSE ;For Osborne 1 cpm3 EQU FALSE ;"Generic" Kermit-80 for CP/M 3.0 (CP/M Plus) ; (terminal required) apmmdm EQU FALSE ;jb Micromodem II in slot 2 ap6551 EQU TRUE ;jb apple with 6551 ACIA in serial interface IF ap6551 ;jb eg. Apple SSC, Videx PSIO, Basis 108 apslot EQU 1 ;jb set equal to slot containing serial card ;jb set to 1 for Basis built-in port ENDIF;jb ap6551 apple EQU apmmdm OR ap6551 ; flag apple system if either selected IF osi OR apple OR osbrn1 OR cpm3 iobyt EQU FALSE inout EQU FALSE ENDIF;osi OR apple OR osbrn1 OR cpm3 ;.. and for Micros, like the MDI, which have "terminals of choice", you must ;select one of these in addition to selecting the micro itself. ;Also select a terminal for "gener" and "cpm3": use "crt" for the true generic. crt EQU FALSE ;Basic CRT, no cursor positioning adm3a EQU FALSE ;Adm3a Display tvi925 EQU FALSE ;TVI925 Display ; (works for Freedom 100 also) [Toad Hall] vt52 EQU FALSE ;VT52 or equivalent (or H19) vt100 EQU FALSE ;VT100 or equivalent ; Toad Hall TAC Trap: If you're going through a TAC, it will ; cough on its Intercept Character (usually a @ (* - 40H)). Sending it ; twice forces the TAC to recognize it as a valid ASCII character, ; and it'll send only one on to the host. If you've SET the TACTrap ; to OFF, it will be a null character, and nothing will happen. If you ; set it on, it will be your selected TAC intercept character (or will ; default to the common intercept char, '@'. ; If you never expect to have to work through such a beastie, just set ; TAC to false and forget all this mess. [Toad Hall] tac EQU FALSE ; gonna work through a TAC? tacval EQU '@' ;Typical TAC intercept character ; Processor speed in units of 100KHz (used for bbII and kpII for timing loops) ;cpuspd EQU 25 ; original Kaypro II: 2.5 MHz cpuspd EQU 40 ; bbII: 4.0 MHz cp4ker EQU FALSE ; building the system-dependent part... IF lasm LINK CP4DEF ENDIF;lasm [Toad Hall] ; If we're still here, must be M80 or MAC80. Collect the rest of ; the sources. INCLUDE CP4DEF.ASM ; common definitions INCLUDE CP4LNK.ASM ; linkage area description INCLUDE CP4SYS.ASM ; system-dependent code and tables END ~; CP4DEF.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This file contains definitions used by both modules of Kermit. ; ; revision history: ; edit 2: July 10, 1984 (CJC) ; Remove defines for TRUE and FALSE, during reorganization for LASM ; compatibility. If we're using LASM, this file is linked by CP4KER ; or CP4TYP, and links to CP4MIT or CP4LNK. Also, push comments around ; a little. ; ; edit 1: May, 1984 (CJC) ; extracted from CPMBASE.M80 version 3.9; modifications are described ; in the accompanying .UPD file. ; ;Symbolic Definitions for some ASCII characters ; soh EQU 01O ;ASCII SOH (Control-A) ctrlc EQU 03O ;ASCII ETX (Control-C) bell EQU 07O ;ASCII BEL (Control-G) bs EQU 10O ;ASCII backspace (Control-H) tab EQU 11O ;ASCII Tab (Control-I) lf EQU 12O ;ASCII Line Feed (CTRL-J) ff EQU 14O ;ASCII Form Feed (CTRL-L) cr EQU 15O ;ASCII Carriage Return (CTRL-M) xon EQU 21O ;ASCII XON (Control-Q) xoff EQU 23O ;ASCII XOFF (Control-S) esc EQU 33O ;ASCII ESCape subt EQU 32O ;ASCII SUB (CTRL-Z) del EQU 177O ;ASCII DELete (rubout) ; ;BDOS calls bdos EQU 0005H ;BDOS entry point, for the following functions: ; ;Function Name Function Input Parameters Output Parameter ;============= ======== ================ ================ ; (ALL Function Numbers are passed in Register C) conin EQU 01H ;Read Console NONE ASCII Char in A conout EQU 02H ;Write Console ASCII Char in E NONE auxin EQU 03H ;Auxiliary input rdrin EQU 03H ;Read Reader NONE ASCII Char in A lstout EQU 05H ;Write List ASCII Char in E NONE dconio EQU 06H ;Direct Con I/O ASCII Char in E I/O Status in A ; if E=0FEH, ; Input if E=0FFH prstr EQU 09H ;Print String String-Address NONE ; in DE (term=$) rdstr EQU 0AH ;Read Buffer Buffer-Address Read Buffer filled ; in DE ; Read Buffer Byte Function ; 1 Maximum Buffer Length ; 2 Current Buffer Length (returned value) ; 3-n Data (returned values) ; consta EQU 0BH ;Console Stat NONE LSB(A)=1 if char ready inbdos EQU 0DH ;Init BDOS NONE NONE logdsk EQU 0EH ;LOG-In disk Value in E NONE ; A=0,B=1,... openf EQU 0FH ;Open File FCB-Addr in DE Byte Addr.of FCB, ; or 0FFH if not closf EQU 10H ;Close File FCB-Addr in DE Byte Addr.of FCB, ; or 0FFH if not sfirst EQU 11H ;Search File FCB-Addr in DE Byte Addr.of FCB(0-3), ; or 0FFH if not snext EQU 12H ;Search next FCB-Addr in DE Byte Addr.of next FCB, ; or 0FFH if not delf EQU 13H ;Delete File FCB-Addr in DE Byte Addr.of FCB(0-3), ; or 0FFH if not readf EQU 14H ;Read Record FCB-Addr in DE 0=successful read ; 1=read past EOF ; 2=reading random data writef EQU 15H ;Write Record FCB-Addr in DE 0=successful write ; 1=ERROR extending ; 2=End of disk data ; 255=No more DIR space makef EQU 16H ;Make File FCB-Addr in DE 0-3= success, ; 255= no more dir space renam EQU 17H ;Rename File FCB-Addr in DE 0-3= success, ; 255= file not found rdlog EQU 18H ;Ret. Log Code NONE Login Vector in HL rddrv EQU 19H ;Read Drive # NONE # of logged in drive in ; (A=0,B=1,C=2....) setdma EQU 1AH ;Set DMA Addr. Addr. of 128 NONE ; byte buffer in DE wrtprt EQU 1CH ;Write prot dsk NONE NONE getrov EQU 1DH ;Get R/O Vect. NONE HL= R/O Vect. value setfat EQU 1EH ;Set File Attr. FCB-Addr.in DE Dir. code in A gtdpar EQU 1FH ;Get DSK par. NONE HL=DPB Address usrcod EQU 20H ;Get/Set Usr.Cd E=0FFH (get) A=current code (get) ; E-code (set) A=no value (set) rrand EQU 21H ;Read Random FCB-Addr in DE A=Return code wrand EQU 22H ;Write Random FCB-Addr in DE 1=read'g unwritten data ; 2=(not used) ; 3=can't close curr. ext ; 4=seek to unwr. ext. ; 5=dir overflow(write) ; 6=seek past End of DSK cflsz EQU 23H ;Comp File Sz. FCB Addr.in DE Rand.Rec.field set to ; File size setrar EQU 24H ;Set Rand. Rec. FCB-Addr.in DE Rand.Rec.field set ; CPM 2 only: punout EQU 04H ;Write Punch ASCII Char in E NONE gtiob EQU 07H ;Get I/O status NONE I/O Status in A ptiob EQU 08H ;Put I/O status I/O Status in E NONE getalv EQU 1BH ;Get All.Vect. NONE All.Vect in HL ; CPM 3 only: auxout EQU 04H ;Auxiliary output auxist EQU 07H ;Get AUXIN: status A=FF if character ; ready, A=0 if none auxost EQU 08H ;Get AUXOUT: status A=FF if ready, A=0 ; if not ready getfs EQU 2EH ;Get free space E=drive # rec free in dma addr ; parevn EQU 00H ;Even parity. parmrk EQU 03H ;Mark parity. parnon EQU 06H ;No parity (eighth bit is data). parodd EQU 09H ;Odd parity. parspc EQU 0CH ;Space parity. defpar EQU parnon ;Default parity. ibmpar EQU parmrk ;IBM COMTEN's parity. fcb EQU 5CH ;Location of File Control Block. fcbext equ fcb+12 fcbrno equ fcb+33 buff EQU 80H ;Location of file output buffer (DMA). bufsiz EQU 80H ;Size of DMA. maxpkt EQU '~'-' '+2O;Maximum size of a packet. maxtry EQU 05O ; Number of retries on a packet. imxtry EQU 20O ; Number of retries send initiate. ; opcodes for command parser cmkey EQU 01H ;Parse a keyword. cmifi EQU 02H ;Parse an input file spec (can be wild). cmofi EQU 03H ;Parse an output file spec. cmcfm EQU 04H ;Parse a confirm. cmtxt EQU 05H ;Parse text. cmifin EQU 10H ;Parse an input file spec (but no ;Error output ; ; If this is being assembled by LASM, we need to LINK to one of two modules; ; if we're not using LASM, no problem. ; CP4KER.ASM defines "cp4ker" TRUE, and CP4TYP.ASM defines it FALSE, so we can ; determine what's going on. IF lasm AND cp4ker ; building CP4KER with LASM? LINK CP4MIT ; yes, chain to next piece. ENDIF;lasm AND cp4ker IF lasm AND NOT cp4ker ; LASM, but not building CP4KER? LINK CP4LNK ; yes, chain to different piece. ENDIF;lasm AND NOT cp4ker  gonna work through a TAC? tacval EQU '@' ;Typical TAC intercept character ; Processor speed in units of 100KHz (used for bbII and kpII for timing loops) ;cpuspd EQU 25 ; original Kaypro II: 2.5 MHz cpuspd EQU 40 ; bbII: 4.0 MHz cp4ker EQU FALSE ; building the system-dependent part... IF lasm LINK CP4DEF ENDIF;lasm [Toad Hall] ; If we're still here, must be M80 or MAC80. Collect the rest of ; the sources. INCLUDE CP4DEF.ASM ; common definitions INCLUDE CP4LNK.ASM ; linkage area description INCLUDE CP4SYS.ASM ; system-dependent code and tables END ~; CP4SYS.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This file contains the system-dependent code and data for KERMIT. ; It will be probably be broken into independent files to generate ; overlays for the various systems, one or more overlay possible ; from each file. For now, we will leave it in one piece. ; ; revision history: ; edit 4: August 8, 1984 ; Running terminal output through the BDOS didn't work so well for ; the Kaypro. Remove the special check at outcon:. ; ; edit 3: August 3, 1984 ; move "mover" to CP4SYS from CP4UTL, so we can use Z80 block move. ; define Z80 true or false when setting up the rest of the parameters. ; (I'm only defining as Z80's the ones I KNOW are Z80's, because I ; don't want to break anything by guessing wrong). Make the values ; stored by sysinit in "speed" match the 16-bit values found in the ; speed table, so we can find them later. ; ; edit 2: July 27, 1984 (CJC) ; Add break capability for Kaypro II and bbII. ; Merge Toad Hall changes: Allow assembly with LASM, add support for ; Morrow Decision I. ; ; edit 1: May, 1984 ; extracted from CPMBASE.M80 version 3.9; modifications are described ; in the accompanying .UPD file. ; ; ; Assembly time message to let me know I'm building the right version. ; LASM generates an 'S' error along with the message, which is messy, but ; better than trying to put everything inside a IF m80 OR mac80 conditional, ; because LASM doesn't like nested IF's, either. IF robin .printx * Assembling KERMIT-80 for the DEC VT180 * ENDIF IF brain .printx * Assembling KERMIT-80 for the Intertec Superbrain * ENDIF IF vector .printx * Assembling KERMIT-80 for the Vector Graphics * ENDIF IF osi .printx * Assembling KERMIT-80 for the Ohio Scientific * ENDIF IF heath .printx * Assembling KERMIT-80 for the Heath/Zenith 89 * ENDIF IF z100 .printx * Assembling KERMIT-80 for the Heath/Zenith Z100 * ENDIF IF apple .printx * Assembling KERMIT-80 for the Apple ][ * ENDIF;apple IF apmmdm .printx * with Z80 Softcard & Micromodem II * ENDIF;apmmdm IF ap6551 .printx * with Z80 Softcard & 6551 ACIA * ENDIF;ap6551 IF trs80 .printx * Assembling KERMIT-80 for the TRS-80 II * ENDIF IF osbrn1 .printx * Assembling KERMIT-80 for the Osborne 1 * ENDIF IF telcon .printx * Assembling KERMIT-80 for the Telcon Zorba * ENDIF IF dmII .printx * Assembling KERMIT-80 for the DECmate II * ENDIF IF gener .printx * Assembling Generic KERMIT-80 * ENDIF IF cpm3 .printx * Assembling Generic KERMIT-80 for CP/M 3.0 * ENDIF IF kpii .printx * Assembling Kaypro II KERMIT-80 * ENDIF IF bbII .printx * Assembling BigBoard II KERMIT-80 * ENDIF IF mdI .printx * Assembling for Morrow Decision I * ENDIF ;mdI [Toad Hall] IF mmdI .printx * Assembling for Morrow Micro Decision I * ENDIF ;mmdI IF mikko .printx * Assembling MikroMikko Kermit-80 * ENDIF ; Also tell what kind of terminal, if any, is selected IF crt .printx * generic CRT selected * ENDIF IF adm3a .printx * ADM3A selected * ENDIF IF tvi925 .printx * TVI925 selected * ENDIF IF vt52 .printx * VT52 selected * ENDIF IF vt100 .printx * VT100 selected * ENDIF ; ;========================================================================= ; I/O Byte assignments (2-bit fields for 4 devices at loc 3) ; ;bits 6+7 LIST field ; 0 LIST is Teletype device (TTY:) ; 1 LIST is CRT device (CRT:) ; 2 LIST is Lineprinter (LPT:) ; 3 LIST is user defined (UL1:) ; ;bits 4+5 PUNCH field ; 0 PUNCH is Teletype device (TTY:) ; 1 PUNCH is high speed punch (PUN:) ; 2 PUNCH is user defined #1 (UP1:) ; 3 PUNCH is user defined #2 (UP2:) ; ;bits 2+3 READER field ; 0 READER is Teletype device (TTY:) ; 1 READER is high speed reader (RDR:) ; 2 READER is user defined #1 (UR1:) ; 3 READER is user defined #2 (UR2:) ; ;bits 0+1 CONSOLE field ; 0 CONSOLE is console printer (TTY:) ; 1 CONSOLE is CRT device (CRT:) ; 2 CONSOLE is in Batch-mode (BAT:);READER = Input, ; LIST = Output ; 3 CONSOLE is user defined (UC1:) ; ;========================================================================= iobyte EQU 03H ;Location of I/O byte ; the basics... IF robin OR gener batio EQU 056H ;I/O byte CON=BAT,LIST=CRT,READER=RDR,PUNCH=PTP defio EQU 095H ;I/O byte CON=CRT,LIST=LPT,READER=RDR,PUNCH=PTP ENDIF;robin OR gener IF gener crtio equ 01010101B ; use CRT: device ptrio equ 01010110B ; use PTR: device ttyio equ 00000000B ; use TTY: device uc1io equ 01010111B ; use UC1: device ur1io equ 01101010B ; use UR1: device ur2io equ 01111110B ; use UR2: device ENDIF;gener IF robin lptio EQU 054H ;I/O byte CON=TTY,LIST=CRT,READER=PTR,PUNCH=PTP gppio EQU 057H ;I/O byte CON=UC1,LIST=CRT,READER=RDR,PUNCH=PTP ENDIF;robin IF dmII batio EQU 042H ;I/O byte CON=BAT,LIST=CRT,READER=RDR defio EQU 081H ;I/O byte CON=CRT,LIST=LPT,READER=RDR ENDIF;dmII IF mikko batio EQU 10110010B ; I/O byte console => serial line defio EQU 10000001B ; I/O byte console => CRT and Keyboard ENDIF;mikko ; ; ; Protocol parameters. Some of these can be changed with commands. ; drpsiz EQU 5EH ;Default receive packet size. (maximum is 5EH) dspsiz EQU 20H ;Default send packet size. (maximum is 5EH) dstime EQU 08H ;Default send time out interval. IF NOT (apple OR osbrn1) drtime EQU 05H ;Default receive time out interval. ENDIF;NOT (apple OR osbrn1) IF apple OR osbrn1 drtime EQU 0AH ; Use longer receive timeout on apple and osborne. ENDIF;apple OR osbrn1 dspad EQU 00H ;Default send padding. drpad EQU 00H ;Default receive padding. dspadc EQU 00H ;Default send padding char. drpadc EQU 00H ;Default receive padding char. dseol EQU CR ;Default send EOL char. dreol EQU CR ;Default receive EOL char. dsquot EQU '#' ;Default send quote char. drquot EQU '#' ;Default receive quote char. dschkt EQU '1' ;Default checksum type ; IF brain baudst EQU 60H ; baudrt EQU 0EF00H ;Memory location where baud rates are stored. mnport EQU 58H ;Modem data port mnprts EQU 59H ;Modem status port output EQU 01H ;Transmitter empty input EQU 02H ;Input data available z80 EQU FALSE ;I don't know... ENDIF;brain IF osi mnport EQU 0CF01H ;Modem data port mnprts EQU 0CF00H ;Modem status port output EQU 02H ;Transmitter empty input EQU 01H ;Input data available z80 EQU FALSE ;I don't know... ENDIF;osi IF vector mnport EQU 04H ;Modem data port mnprts EQU 05H ;Modem status port output EQU 01H ;Transmitter empty input EQU 02H ;Input data available z80 EQU FALSE ;I don't know... ENDIF;vector IF heath mnport EQU 330O ;Modem data port mnprts EQU 335O ;Modem status port output EQU 20H ;Transmitter empty input EQU 01H ;Input data available z80 EQU FALSE ;I don't know... ENDIF;heath IF z100 mnport EQU 0ECH ;Modem data port mnprts EQU 0EDH ;Modem status port output EQU 01H ;Transmitter empty input EQU 02H ;Input data available z80 EQU FALSE ;I don't know... ENDIF;z100 IF trs80 ;NEEDS display definition (e.g. trs80lb or trs80pt) mnport EQU 0F4H ;Modem data port (0F5H for port B) mnprts EQU 0F6H ;Modem status port (0F7H for port B) output EQU 04H ;Transmitter empty input EQU 01H ;Input data available z80 EQU FALSE ;I don't know... ENDIF;trs80 IF apmmdm ;APPLE Slot 2 contains Micromodem II. MNPORT EQU 0E0A7H ;Communications Port. mnprts EQU 0E0A6H ;Communications Port Status. mnmodm EQU 0E0A5H ;Modem Control Port. orgmod EQU 8EH ;Modem Originate Mode. OUTPUT EQU 02H ;Output Buffer Empty. INPUT EQU 01H ;Input Register Full. apinc1 EQU 03H ;First Init Character for 6850 ACIA (Reset) apinc2 EQU 11H ;Second Init Character for ACIA (8-bits) apoffh EQU 80H ;Set if OFFHOOK AP300 EQU 1 ;300 Baud z80 EQU TRUE ;Z80 Softcard ENDIF;apmmdm IF ap6551 ;jb mnport EQU 0E088H+(10H*apslot) ;jb Communications Port. mnprts EQU 0E089H+(10H*apslot) ;jb Communications Port Status. mnprtc EQU 0E08BH+(10H*apslot) ;jb Communications Control mnprtm EQU 0E08AH+(10H*apslot) ;jb Communications Master (command) output EQU 10H ;jb Output Buffer Empty. input EQU 08H ;jb Input Register Full. mncinb EQU 18H ;jb Control Port Initialization Byte ;jb (8-bit, no parity, 1-stop, 1200 baud) mnminb EQU 0BH ;jb Master Port Initialization Byte ;jb (DTR, RTS, no interrupts) z80 EQU TRUE ;Z80 Softcard ENDIF;ap6551 IF osbrn1 ;Osborne 1 uses 6850 ACIA, but memory mapped. Derived from Apple. BAUDRT EQU 0EFC1H ;Memory location where baud rates are stored. OSTOP EQU 4000H ;Where we move OSMOVE to at startup OSPORT EQU 2A01H ;Communications Port. OSPRTS EQU 2A00H ;Communications Port Status. OUTPUT EQU 02H ;Output Buffer Empty. INPUT EQU 01H ;Input Register Full. OSBIN1 EQU 57H ;First Init Character for 6850 ACIA (Reset) ;(I would have thought 03, but prom code writes 57 there) OSBI12 EQU 55H ;Second Init Character for ACIA (8-bits, 1200) OSBI03 EQU 56H ;Second init char. for ACIA (8 bits, 300) ;(don't ask.. I don't know why SETUP writes 55 and 56 either) z80 EQU FALSE ;I don't know... ENDIF;osbrn1 IF telcon MNPORT EQU 20H ;Modem data port MNPRTS EQU 21H ;Modem status port OUTPUT EQU 01H ;Transmitter empty INPUT EQU 02H ;Input data available z80 EQU FALSE ;I don't know... ENDIF;telcon IF robin ;Those definitions below that are commented out are just for information ;***** NOT generally found in distributed documentation **** ;pbausl EQU 90H ;The Baud-Rate register. prntst EQU 49H ;Printer ;prndat EQU 48H contst EQU 41H ;Console ;condat EQU 40H gentst EQU 51H ;General port. ;gendat EQU 50H comtst EQU 59H ;COMM-Port ;comdat EQU 58H ;output EQU 01H ;Output ready bit. ;input EQU 02H ;Input ready bit. z80 EQU TRUE ; This one's a Z80. ENDIF;robin IF kpii mnport equ 04h ; Modem data port mnprts equ 06h ; Modem status port output equ 04h ; Transmit buffer empty input equ 01h ; Receive data available baudrt equ 00h ; Baud rate port for channel A z80 EQU TRUE ; This one's a Z80. ENDIF;kpii IF bbII mnport equ 80h ; Modem data port (SIO channel A) mnprts equ 81h ; Modem status port output equ 04h ; Transmit buffer empty input equ 01h ; Receive data available baudrt equ 89h ; Baud rate port for channel A z80 EQU TRUE ; This one's a Z80. ENDIF;bbII IF mmdI ;Morrow MicroDecision - the single-board one mnport EQU 0FEH ;Morrow Printer UART data port mnprts EQU 0FFH ;Morrow Printer UART command/status output EQU 01H ;Output ready bit. input EQU 02H ;Input ready bit. ;Note: Needs terminal definition (vt100, vt52, tvi925, adm3a or crt above) z80 EQU FALSE ;I don't know... ENDIF;mmdI IF mdI ;Morrow Decision I - the big sucker mnport equ 48H ; Modem data port. mnprts equ 4DH ; Modem status port. output equ 20H ; Transmitter empty. input equ 1 ; Input data available. mbase equ 48H ; Base address of Multi I/O port ; selector area. grpsel equ 4FH ; Group select port. rbr equ 48H ; Read Data Buffer. group equ 1 ; Multi I/O Group byte for serial ports. congrp equ 1 ; Serial Port 1 for console mdmgrp equ 3 ; Serial Port 3 for modem. ; Following are needed for baud rate changes...[Toad Hall] dlm equ 49H ; Baud Rate Divisor (Most Sig Bit) dll equ 48H ; Baud Rate Divisor (Least Sig Bit) ier equ 49H ; Interrupt Enable Register lcr equ 4BH ; Line Control Register lsr equ 4DH ; Line Status Register msr equ 4EH ; Modem Status Register dlab equ 80H ; Divisor Latch Access Bit wls0 equ 1 ; Word Length Select Bit 0 wls1 equ 2 ; Word Length Select Bit 1 for 8 bit word stb equ 4 ; Stop bit count - 2 stop bits imask equ 0 ; Interrupt mask (all disabled) z80 EQU TRUE ; This one's a Z80. ENDIF ;mdI NOTE: needs terminal definition. [Toad Hall] IF mikko sioac EQU 0FF12H ;SIO channel A register(s) address sioo3 EQU 01000001B ;SIO Write Reg. 3 original setup (?) ;RX 7 bits,synch mode bits 0,RX enable sion3 EQU 11001111B ;SIO Write Reg. 3 KERMIT setup ;RX 8 bits,synch mode bits 0,RX enable sioo4 EQU 01001111B ;SIO Write Reg. 4 original setup (?) ;X16 clock,8 bit synch(ignored), ;2stop bits,par even(on) sion4 EQU 01000100B ;SIO Write Reg. 4 KERMIT setup ;X16 clock,8 bit synch(ignored), ;1stop bit,par off sioo5 EQU 10101010B ;SIO Write Reg. 5 original setup (?) ;DTR,TX 7 bits,TX enable,RTS sion5 EQU 11101010B ;SIO Write Reg. 5 KERMIT setup ;DTR,TX 8 bits,TX enable,RTS txclk EQU 0FF30H ;Baud rate generator (CTC) for transmitter rxclk EQU 0FF31H ;Baud rate generator (CTC) for receiver chmask EQU 0F1F2H ;Mask byte address for SIO ch. A reception z80 EQU TRUE ;It's got a SIO and a CTC, it must be a Z80 ENDIF;mikko IF robin OR dmII z80 EQU TRUE ; This one's a Z80 ENDIF;robin OR dmII  IF gener OR cpm3 ; To be truly generic, we must assume 8080. z80 EQU FALSE ENDIF;gener OR cpm3 ; IF brain OR osi OR apple OR telcon defesc EQU ']'-100O ;The default escape character. ENDIF;brain OR osi OR apple OR telcon IF vector defesc EQU '~' ;Vector can't type ']'. ENDIF;vector IF robin OR dmII OR mikko OR heath OR z100 OR osbrn1 OR kpII defesc EQU '\'-100O ;The default is Control \ -- it's easier B.E. ENDIF;robin OR dmII OR mikko OR heath OR z100 OR osbrn1 OR kpII IF crt OR vt100 OR vt52 OR tvi925 OR adm3a defesc EQU '\'-100O ;Still Control-\ (just ran out of room...) ENDIF;crt OR vt100 OR vt52 OR tvi925 OR adm3a IF trs80 defesc EQU '_'-100O ;CTRL-_ (Down-arrow on TRS-80 keyboard) ENDIF;trs80 ; Select initial setting for VT-52 emulation flag. IF crt ; If dumb or unknown console, vtval EQU 0FFH ; we can't support VT52 emulation ENDIF;crt IF heath OR z100 OR telcon OR vt52 ; If console looks like (or is) VT52 vtval EQU 0 ; we don't need VT52 emulation ENDIF;heath OR z100 OR telcon OR vt52 IF robin OR dmII OR vt100 ; If console looks like VT100 vtval EQU 0 ; we probably don't want VT52 emulation ENDIF;robin OR dmII OR vt100 ; If none of the above, default to VT52-EMULATION ON. IF NOT (crt OR heath OR z100 OR telcon OR vt52 OR robin OR dmII OR vt100) vtval EQU 1 ENDIF;NOT (crt OR heath OR z100 OR telcon OR vt52 OR robin OR dmII OR vt100) ; Set the fuzzy timeout value. Range is 1 (VERY short) through 0ffffH to zero ; (maximum). The actual duration is a function of the loop length and the ; processor speed. For now, we'll make it zero for everybody, but feel free ; to change it for your system. fuzval EQU 0 ; ; ; System-dependent initialization ; Called once at program start. sysinit: lxi d,cfgmsg ; "configured for " call prtstr lxi d,sysver ; get configuration we're configured for call prtstr ; print it. ; ; If we're set up to do special terminal handling, say what kind ; of terminal we expect... (unless it's the generic 'crt') IF adm3a OR tvi925 OR vt52 OR vt100 lxi d,witmsg ; " with " call prtstr lxi d,ttytyp ; terminal type call prtstr ENDIF;adm3a OR tvi925 OR vt52 OR vt100 call prcrlf ; print CR/LF ; ; now, to work... ; IF iobyt call iniadr ;Initialize the BIOS addresses mvi c,gtiob ;Get current I/O byte call bdos ;From CP/M sta coniob ;Remember where console is ENDIF;iobyt IF osbrn1 lxi d,ostop ;where we're moving it to lxi h,osmove ;what we're moving mvi b,osmct ;How many bytes we're moving call mover lda baudrt ; Find out what speed is current ani 1 mvi a,osbi03 ; assume 300 baud jz osstr1 mvi a,osbi12 ; nope, it's 1200. osstr1: sta speed ; save initial speed sta speed+1 ; as 16 bits, to match speed table entries mvi d,a mov e,a ; get initial speed in DE call sysspd ;set up parity etc. ENDIF;osbrn1 IF kpii OR bbII lxi d,siotbl ; Load the address of the status able mvi c,siolen ; Length of status table siolup: ;Loop back here for each command byte ldax d ; Load the first byte into A inx d ; Index the pointer out mnprts ; Send it to the status port dcr c ; Decrement the byte counter jnz siolup ; Jump back for more commands ENDIF;kpii or bbII IF mikko lxi d,mintbl ;Address of KERMIT Reg values (what) mvi c,minlen ;Length of table (how many) lxi h,sioac ;Send data to ch. A SIO registers (to where) call movmik mvi a,0FFH ;Set ch. A mask to use all bits sta chmask ENDIF;mikko IF brain lda baudrt ; fetch current baud rate ani 0F0H ; extract left nibble rrc ; shift right 4 places rrc rrc rrc sta speed ; store as comm port speed sta speed+1 ; (16 bits, to match speed table entries) ENDIF;brain IF mdI lxi h,96 ;Default 1200 baud modem port speed shld speed ;Store as modem port speed call sysspd ;Initialize the port ENDIF;mdI [Toad Hall] IF ap6551 lda mnprtc ; read control port ani 0fH ; extract low order nybble sta speed ; store as comm line speed sta speed+1 ; (16 bits, to match speed table entries) mvi a,mnminb ;jb initialization routine sta mnprts ;jb sta mnprtm ;jb initialize master (command) port mvi a,mncinb ;jb sta mnprtc ;jb initialize control port ENDIF;ap6551 ret ; IF iobyt ; This one is hopefully the last "improvement" in view of GENERIC ;Kermit. It uses for Character-I/O the BIOS-routines ( instead of the ;"normal" BDOS routines. What does it give us (hopefully) : More speed, ;higher chance of success ( I/O byte implemented in BIOS [if at all]), ;but no "extra" device handling - that's done by BDOS. ; ; How do we "get" the call-adresses? Location 0 has a JMP Warm-Boot ;in CP/M which points into the second location of the BIOS JMP-Vector. The ;next three locations of the JMP-Vector point to the CONSTAT,CONIN,CONOUT ;BIOS-routines. CONOUT wants the character in C. ; ;- Bernie Eiben iniadr: lhld 1 ;get BIOS Warmstart-address lxi d,3 ;next adress is CONSTAT in BIOS dad d shld bconst+1 ;stuff it into the call-instruction lxi d,3 ;next adress is CONIN in BIOS dad d shld bconin+1 ; lxi d,3 ;next adress is CONOUT in BIOS dad d shld bcnout+1 lxi d,3 ;next address is LIST in BIOS dad d shld blsout+1 ret ;And return bconst: jmp $-$ ;Call BIOS directly (filled in by iniadr) bconin: jmp $-$ ;Call BIOS directly (filled in by iniadr) bcnout: jmp $-$ ;Call BIOS directly (filled in by iniadr) blsout: jmp $-$ ; .... ENDIF;iobyt IF mikko ;currently for MIKROMIKKO only ; copy command block into memory-mapped SIO. movmik: di ;disable interrupts movmk1: ldax d ;Get a register value mov m,a ;Output it inx d ;Next value dcr c ;Decrement counter jnz movmk1 ;Repeat until done ei ret ENDIF;mikko ; IF osbrn1 osmove: osflag equ 0EF08H ;Osborne 1 Bank-2 flag ; ; return modem status in A ; OSLDST EQU ostop-osmove+$ DI OUT 0 LDA osprts ;Read the status port OUT 1 EI ret ; ; set modem status from A ; OSSTST equ ostop-osmove+$ DI OUT 0 STA osprts ;Write the control port jmp osstex ; ; read character from modem into A ; OSLDDA equ ostop-osmove+$ DI OUT 0 LDA osport OUT 1 EI ret ; ; output character in A to modem ; OSSTDA equ ostop-osmove+$ DI OUT 0 STA osport osstex equ ostop-osmove+$ OUT 1 mvi a,1 sta osflag EI ret osmct equ $-osmove ENDIF;osbrn1 IF kpii OR bbII ; List of commands to set up SIO channel A for asynchronous operation. siotbl: DB 18H ; Channel reset DB 18H ; another, in case register 0 wasn't selected DB 04H ; Select register 4 DB 44H ; 1 stop bit, clock*16 DB 01H ; Select register 1 DB 00H ; No interrupts enabled DB 03H ; Select register 3 DB 0C1H ; Rx enable, 8 bit Rx character DB 05H ; Select register 5 DB 0EAH ; Tx enable, 8 bit Tx character, ; raise DTR and RTS siolen equ $-siotbl ; length of command list ENDIF;kpii or bbII IF mikko ; command list to set SIO chip back to normal state miotbl: db 3 ;reg. 3 db sioo3 db 5 ;reg. 5 db sioo5 db 4 ;reg. 4 db sioo4 db 0 ;reselect reg. 0 miolen equ $-miotbl ;MikroMikko SIO table length (original values) ; command list to set up SIO chip for operation with Kermit mintbl: db 3 ;reg. 3 db sion3 db 5 ;reg. 5 db sion5 db 4 ;reg. 4 db sion4 db 0 ;reselect reg. 0 minlen equ $-mintbl ;MikroMikko SIO table length (KERMIT values) ENDIF;mikko ; ; ; system-dependent termination processing ; If we've changed anything, this is our last chance to put it back. sysexit: IF mikko lxi d,miotbl ;Load the adress of original reg values mvi c,miolen ;Length of table lxi h,sioac ;Send data to ch A SIO registers call movmik mvi a,07FH ;Set ch A mask to use just 7 bits sta chmask ENDIF;mikko ret ; ; system-dependent processing for start of CONNECT command ; syscon: IF apmmdm call ckdial ;See if dialing is required. jmp kermit ;Go to command loop if aborted. ENDIF;apmmdm IF robin OR trs80 ;For Robin and TRS80, add some more info lxi d,conmsg ; about obscure key combinations call prtstr ENDIF;robin OR trs80 IF osbrn1 ;*** This is Software dependent *** lhld 1 ;Modify back-arrow code to DELETE mvi l,0 ;Get BIOS-start address lxi d,85H ;Adress for key-code = XX85H dad d mov e,m ;Get it in DE inx h mov d,m xchg ;Memory pointer to HL mvi m,del ;modify the code ENDIF;osbrn1 ret conmsg: ; Messages printed when entering transparent (CONNECT) mode: IF robin ; for Robin, control-S key is hidden db ' (Type Left Arrow to send CTRL-S)',cr,lf,'$' ENDIF;robin IF trs80 ; for TRS-80, the preferred escape key is hidden db ' (Control-_ is the Down-Arrow key on the TRS-80 keyboard)' db cr,lf,'$' ENDIF;trs80 ; IF apmmdm ;This code was mostly taken from ; APMODEM.ASM V2.1 ; Based on MODEM.ASM by Ward Christensen ; Modified for the Apple ][ by Gordon Banks 1-Jan-81 ; Micromodem ][ dialer option by Dav Holle 2-Feb-81 ; Code modified for KERMIT by Scott Robinson 14-Oct-82 ; ;Come here to see if we need to dial a number. ; ckdial: lda mnport ;access the data port lda mnprts ;check status ani 4 ;do we already have carrier? jz rskp ;Yes, just continue xra a ;Hangup Phone for starters sta mnmodm lxi b,1000 ;Delay for a second call delay mvi a,8FH ;orgmod+ap300+apoffh sta holdd ;storing mode for after dialing mvi A,8DH ;Go Offhook to start dialing sequence sta mnmodm mvi a,apinc1 ;Init ACIA sta mnport mvi a,apinc2 ;Set ACIA bits per character sta mnport lxi b,2500 ;wait 2.5 seconds for dial tone call delay lxi d,dialms ;Ask the user for the number call prtstr ; gtdial: mvi c,conin ;Get a character call bdos push psw ;save it cpi 30H ;is it big enough to dial? jc dialed ;no cpi 3AH ;is it too big to dial? jnc dialed ;yes ani 0FH ;ok, it's a digit, get its value jnz dialnz ;dial nonzero digits as-is mvi A,10 ;dial zero as ten ; dialnz: mov e,a ;count pulses in E-reg dopuls: mvi a,0DH ;put it on-hook sta mnmodm lxi b,61 ;61-millisec pulse call delay mvi a,8DH ;take it off-hook again... sta mnmodm lxi b,39 ;39-millisec delay between pulses call delay dcr e ;any more pulses to do? jnz dopuls ;yep, do 'em lxi b,600 ;delay 600 msecs between digits call delay ; dialed: pop psw ;get back the char cpi cr ;do we have a CR (done dialing)? jnz gtdial ;no, keep on dialin' lxi d,dialm2 call prtstr tictoc: mvi c,dconio ;Direct console input. mvi e,0FFH call bdos ora a ;Have a charcter? jnz nodial ;If so we abort lda mnport ;access the data port lda mnprts ;get modem status ani 4 ;carrier? jnz tictoc ;No ; lda holdd ;get the old modem control byte sta mnmodm ;turn our carrier on lxi d,dialm3 call prtstr jmp rskp nodial: xra a ;Hangup the modem. sta mnmodm ret ;Return to abort the command. ; holdd: db 0 ;Modem setup code dialms: DB 'Number to Dial: $' dialm2: DB CR,LF,'Awaiting Carrier....(any key aborts)$' dialm3: DB cr,lf,'Connected.',CR,LF,'$' ; ;DELAY wait for the number of millisecs in B,C ; delay: push b ;save B,C push d ;save D,E inr b ;bump B for later DCR ; delay1: mvi e,126 ;delay count for 1 millisec (Apple Z80 ;clock=2.041MHz) ; delay2: dcr e ;count jnz delay2 ;down ; dcr c ;more millisecs? jnz delay1 ;yes dcr b ;no - more in hi byte? jnz delay1 ;yes pop d ;no, restore D,E pop b ; restore B,C ret ENDIF;apmmdm ; ; ; syscls - system-dependent close routine ; called when exiting transparent session. ; syscls: IF osbrn1 lhld 1 ;Modify back-arrow code to BACKSPACE mvi l,0 ;Get BIOS address lxi d,85H ;Address for key-code =XX85H dad d mov e,m ;Get it in DE inx h mov d,m xchg ;Address to HL mvi m,bs ;Modify code ENDIF;osbrn1 ret ; ; ; sysinh - help for system-dependent special functions. ; called in response to ?, after listing all the ; system-independent escape sequences. ; sysinh: IF apmmdm OR robin OR dmII OR bbII OR kpii lxi d,inhlps ; we got options... call prtstr ; print them. ENDIF;apmmdm OR robin OR dmII OR bbII OR kpii ret ;additional, system-dependent help for transparent mode ; (two-character escape sequences) inhlps: IF apmmdm db cr,lf,'D Close and disconnect the connection$' ENDIF;apmmdm IF robin OR dmII OR bbII OR kpii db cr,lf,'B Transmit a BREAK$' ENDIF;robin OR dmII OR bbII OR kpii ; ; sysint - system dependent special functions ; called when transparent escape character has been typed; ; the second character of the sequence is in A (and in B). ; returns: ; non-skip: sequence has been processed ; skip: sequence was not recognized sysint: ani 137O ; convert lower case to upper, for testing... IF apmmdm cpi 'D' ;Disconnect Modem? jnz intc00 ;No. xra a ;Yes, hangup the modem sta mnmodm ret ; command has been executed intc00: ENDIF;apmmdm IF robin OR dmII OR kpII OR bbII cpi 'B' ; send break? jz sendbr ; yes, go do it. return nonskip when through. ENDIF;robin OR dmII OR kpII OR bbII jmp rskp ; take skip return - command not recognized. ; IF robin ;Definitions & code to send a BREAK (ungenerically, no other way). comctl equ 59h ;VT180 communications port crtctl equ 41h ;VT180 crt port ;VT180 serial port command bits txe equ 1 ;transmit enable dtr equ 2 ;dtr on rxe equ 4 ;rx enable sndbrk equ 8 rerr equ 10h ;reset error rts equ 20h ;RTS on reset equ 40h ;port reset ;Send a break to the communications port. ; sendbr: lxi h,38500 ;250 ms(?) lda prtadr ;Get address of selected port mov c,a ;Into C mvi a,sndbrk+dtr ; OUT C,A ;Want to send to port addressed by C db 0EDH,079H ;Op code for above instruction sndbr1: dcx h ;timing loop... mov a,l ora h jnz sndbr1 ;...until over lda prtadr ;Get the address for the port mov c,a ;Into C mvi a,txe+dtr+rxe+rerr+rts ;enable tr/rc, dtr, reset error ; out c,a ;Z-80 only instruction db 0EDH,079H ;Op code for above instruction out contst ;reset ports ret ENDIF;robin ; IF dmII ;[jd] this added to send break on DECmate ; DECmate command codes for 6120 I/O processor oboff equ 3fh ; offset of outbyt routine for 6120 prtctl equ 02h ; port control brdat equ 06h ; data to tell 6120 to send a break brdur equ 30 ; duration, 30 = 300 ms. sendbr: lxi b,(brdat * 100h) + prtctl ; c/prtctl, b/brdat call outbyt lxi b,brdur*100h ; b/duration, c/0 ; fall through into outbyt outbyt: lhld 1 ; get warm boot address lxi d,oboff ; offset of outbyt routine dad d ; compute address pchl ; branch there (a callret) ENDIF;dmII ; IF kpII OR bbII ;[cjc] send break on Kaypro and bbII ; Officially, a "break" is 300 milliseconds of "space" (idle line is ; "mark"). (or maybe 200 milliseconds; I forget.) The timing isn't ; usually that critical, but we'll make an attempt, at least. Sending ; too long a break can cause some modems to hang up. sendbr: ; First, make sure the transmitter is really empty. (The SIO sets ; "transmitter buffer empty" when it can accept another character; ; the previous character is still being shifted onto the line. ; Another status bit, "all done", is set to indicate that the ; transmitter is really idle. sndbr1: mvi a,1 ; select Read Register 1 out mnprts in mnprts ; read the contents ani 1 ; test "all done" flag jz sndbr1 ; loop until it's nonzero. ; ; Next, set the "send break" bit to start the transmitter spacing. mvi a,5 ; select Write Register 5 out mnprts mvi a,0FAH ; Tx enable, 8 bit Tx character, Send Break, out mnprts ; DTR and RTS on. ; ; Now, delay for 30 hundredths of a second mvi a,30 ; delay count call delay ; ; Time's up. Put transmitter back in normal state (data byte is the ; same as the one in siotbl: for Write Register 5) and return. mvi a,5 ; select Write Register 5 out mnprts mvi a,0EAH ; Tx enable, 8 bit Tx character, out mnprts ; DTR and RTS on. ret ; done. ; ; Delay routine. Called with time (hundredths of seconds) in A. ; The inner loop delays 1001 T-states, assuming no wait states are ; inserted; this is repeated CPUSPD times, for a total delay of just ; over 0.01 second. (CPUSPD should be set to the system clock rate, ; in units of 100KHz: for an unmodified Kaypro II, that's 25 for ; 2.5 MHz. Some enterprising soul could determine whether or not the ; Kaypro actually inserts a wait state on instruction fetch (a common ; practice); if so, the magic number at delay2 needs to be decreased. ; (We also neglect to consider time spent at interrupt level). ; ; called by: sendbr ; destroys BC delay: mvi c,cpuspd ; Number of times to wait 1000 T-states to ; make .01 second delay delay2: mvi b,70 ; Number of times to execute inner loop to ; make 1000 T-state delay delay3: dcr b ; 4 T-states (* 70 * cpuspd) jnz delay3 ; 10 T-states (* 70 * cpuspd) dcr c ; 4 T-states (* cpuspd) jnz delay2 ; 10 T-states (* cpuspd) ; total delay: ((14 * 70) + 14) * cpuspd ; = 1001 * cpuspd + call/return overhead. ret ENDIF;kpII OR bbII ; ; ; sysflt  - system-dependent filter ; called with character in E. ; if this character should not be printed, return with A = zero. ; preserves bc, de, hl. ; note: ,,, and are always discarded. sysflt: mov a,e ; get character for testing IF mikko cpi 'O'-100O ;Control-O's lock keyboard rnz ; if not control-O, it's ok. xra a ; don't allow control-O out. ENDIF;mikko ret ; ; ; system-dependent processing for BYE command. ; for apmmdm, hang up the phone. sysbye: IF apmmdm xra a ;Hangup our end, too. sta mnmodm ENDIF;apmmdm ret ; ; This is the system-dependent command to change the baud rate. ; DE contains the two-byte value from the baud rate table; this ; value is also stored in 'speed'. sysspd: ; Set the speed for the Brain IF brain lda baudrt ;Get the present baud rates. ani 0fH ;turn off the left mov d,a ;Set it aside. mov a,e ;Get the new baud rate. rlc ;Shift left 4 places. rlc rlc rlc ora d ; combine with the old baud rate  sta baudrt ;Store the new baud rates. out baudst ;Set the baud rates. ret ENDIF;brain ; Set the speed for the Osborne I IF osbrn1 mvi a,osbin1 ;Reset the ACIA call osstst ;Write the control port osbs1: inr c ;Waiting loop jnz osbs1 mov a,e ; get the specified speed jmp osstst ;Write the control reg. ENDIF;osbrn1 ; Set the speed for bigboard II IF bbII di ; don't let anything between the data bytes mvi a,01000111b ; get the command byte (load time constant) out baudrt ; output it to CTC mov a,e ; Get the parsed value. out baudrt ; Tell the baud rate generator. ei ; end of critical section ret ENDIF;bbII ; Set the speed for kaypro II IF kpII mov a,e ; get the parsed value out baudrt ; Tell the baud rate generator. ret ENDIF;kpII ; Set the speed for MicroMikko. DE is baud rate multiplier IF mikko di lxi h,txclk mov m,d ;LSB first (swapped in memory) mov m,e ;MSB last lxi h,rxclk mov m,d mov m,e mvi b,0 ;"modifier" for 1 stop bit mvi a,2 ;Test MSB of speed >2 (110 bps or less) cmp e jp miksp1 mvi b,00001000B ;"modifier" for 2 stop bits miksp1: mvi a,4 ;Select SIO Reg 4 lxi h,sioac mov m,a mvi a,sion4 ;Get values ora b ;Add modifier mov m,a ;Set value (stop bits) ei ret ENDIF;mikko ; Set the speed for Apple with 6551 ACIA IF ap6551 lda mnprtc ;jb read control port ani 0F0H ;jb zap low order nybble ora e ;jb put rate in low order nybble sta mnprtc ;jb send to control port ret ENDIF;ap6551 ; Set the speed for the Decision I IF mdI call selmdm ;Let's be absolutely sure, huh? mvi a,dlab+wls1+wls0+stb ;Set data latch access bit out lcr ;Out to Line Control Register lhld speed ;Load baudrate multiplier xchg mov a,d ;Get low order byte for baud rate out dlm ;Out to the MSB divisor port mov a,e ;...and the high order byte out dll ;Out to the LSB divisor port mvi a,wls1+wls0+stb ;Enable Divisor Access Latch out lcr ;Out to ACE Line Control Register xra a ;Clear A out ier ;Set no interrupts out lsr ;Clear status in msr ;Clear Modem Status Register in lsr ;Clear Line Status Register in rbr ;Clear Receiver Buffers in rbr ret ENDIF ;mdI [Toad Hall] ; Speed tables ; (Note that speed tables MUST be in alphabetical order for later ; lookup procedures, and must begin with a value showing the total ; number of entries. The speed help tables are just for us poor ; humans. ; db string length,string,divisor (2 identical bytes or 1 word) ; [Toad Hall] IF kpii OR brain ;(can brain handle 19200? fingers can't...) spdtbl: db 10h ;16 entries db 03h,'110$', 02h,02h db 04h,'1200$', 07h,07h db 05h,'134.5$', 03h,03h db 03h,'150$', 04h,04h db 04h,'1800$', 08h,08h db 05h,'19200$', 0fh,0fh db 04h,'2000$', 09h,09h db 04h,'2400$', 0ah,0ah db 03h,'300$', 05h,05h db 04h,'3600$', 0bh,0bh db 04h,'4800$', 0ch,0ch db 02h,'50$', 00h,00h db 03h,'600$', 06h,06h db 04h,'7200$', 0dh,0dh db 02h,'75$', 01h,01h db 04h,'9600$', 0eh,0eh sphtbl: db cr,lf,' 50 75 110 134.5 150 300 600 1200' db cr,lf,' 1800 2000 2400 3600 4800 7200 9600 19200$' ENDIF;kpii OR brain IF bbII spdtbl: db 8 ; 8 entries db 04h,'1200$', 20h,20h db 05h,'19200$', 02h,02h db 04h,'2400$', 10h,10h db 03h,'300$', 80h,80h db 05h,'38400$', 01h,01h db 04h,'4800$', 08h,08h db 03h,'600$', 40h,40h db 04h,'9600$', 04h,04h sphtbl: db cr,lf,' 300 600 1200 2400 4800 9600 19200 38400$' ENDIF;bbII IF mikko spdtbl: db 9h ;9 entries db 03h,'110$' dw 0369h db 04h,'1200$' dw 0050h db 03h,'150$' dw 0280h db 04h,'2400$' dw 0028h db 03h,'300$' dw 0140h db 04h,'4800$' dw 0014h db 03h,'600$' dw 00A0H db 02h,'75$' dw 0500h db 04h,'9600$' dw 000ah sphtbl: db cr,lf,' 75 110 150 300 600 1200 2400 4800 9600$' ENDIF;mikko IF osbrn1 spdtbl: db 02h ;2 entries db 04h,'1200$', OSBI12,OSBI12 db 03h,'300$', OSBI03,OSBI03 sphtbl: db cr,lf,' 300',cr,lf,' 1200$'  ENDIF;osbrn1 IF ap6551 ;jb spdtbl: db 0DH ;jb 13 entries db 03H,'110$', 03H,03H ;jb db 04H,'1200$', 08H,08H ;jb db 05H,'134.5$', 04H,04H ;jb db 03H,'150$', 05H,05H ;jb db 04H,'1800$', 09H,09H ;jb db 05H,'19200$', 0FH,0FH ;jb db 04H,'2400$', 0AH,0AH ;jb db 03H,'300$', 06H,06H ;jb db 04H,'3600$', 0BH,0BH ;jb db 04H,'4800$', 0CH,0CH ;jb db 03H,'600$', 07H,07H ;jb db 04H,'7200$', 0DH,0DH ;jb db 04H,'9600$', 0EH,0EH ;jb sphtbl: db cr,lf,' 110 134.5 150 300 600 1200 1800' db cr,lf,' 2400 3600 4800 7200 9600 19200$' ENDIF;ap6551 IF mdI spdtbl: db 0dh ; 13 entries db 03h, '110$' dw 1047 db 04h, '1200$' dw 96 db 03h, '150$' dw 768 db 05h,'19200$' dw 6 db 04h, '2400$' dw 48 db 03h, '300$' dw 384 db 05h,'38400$' dw 3 db 03h, '450$' dw 288 db 04h, '4800$' dw 24 db 05h,'56000$' dw 2 db 03h, '600$' dw 192 db 02h, '75$' dw 1536 db 04h, '9600$' dw 12 sphtbl: db cr,lf,' 75 110 150 300 450 600 1200' db cr,lf,' 2400 4800 9600 19200 38400 56000$' ;(Lord knows what you'll be communicating with at 56000 baud, but the ;Multi-I/O board literature says it'll do it, so what the heck.... ;might as well throw it in here just to show off...sure hope the ;port don't melt...) ENDIF ;mdI [Toad Hall] IF NOT (brain OR osbrn1 OR bbII OR kpII OR mikko OR ap6551 OR mdI) spdtbl equ 0 ; SET BAUD not supported. sphtbl equ 0 ENDIF;NOT (brain OR osbrn1 OR bbII OR kpII OR mikko OR ap6551 OR mdI) ; ; This is the system-dependent SET PORT command. ; HL contains the argument from the command table. sysprt: IF iobyt mov a,m ;Get the I/O byte sta prtiob ;Save the desired IO byte for this port inx h ;Point at next entry mov a,m ;Get the output function sta prtfun ;Save it ENDIF;iobyt IF iobyt AND robin inx h ;Point at next entry mov a,m ;Get the hardware address for the port sta prtadr ;Store it ENDIF;iobyt AND robin ret ; ; ; Port tables for GENERIC CPM 2.2 IF gener ; help text prhtbl: db cr,lf,'CRT device' db cr,lf,'PTR device' db cr,lf,'TTY device' db cr,lf,'UC1 device' db cr,lf,'UR1 device' db cr,lf,'UR2 device$' ; command table prttbl: db 06H ;Six devices to choose from db 03H,'CRT$' dw crtptb db 03H,'PTR$' dw ptrptb db 03H,'TTY$' dw ttyptb db 03H,'UC1$' dw uc1ptb db 03H,'UR1$' dw ur1ptb db 03H,'UR2$' dw ur2ptb ; port entry table ; table entries are: ; db iobyte-value, BDOS output function, reserved crtptb: db crtio,conout,0 ptrptb: db ptrio,punout,0 ttyptb: db ttyio,conout,0 uc1ptb: db uc1io,conout,0 ur1ptb: db ur1io,punout,0 ur2ptb: db ur2io,punout,0 ENDIF;gener ; ; ; Port tables for DECmate II or MicroMikko ; IF dmII OR mikko ; help text prhtbl: db cr,lf,'COMMUNICATIONS port$' ; command table prttbl: db 01H ;Only one port known at this point db 0EH,'COMMUNICATIONS$' dw comptb ;address of info ; port entry table ; table entries are: ; db iobyte-value, BDOS output function, reserved comptb: db batio,punout,0 ENDIF;dmII OR mikko ; ; ; Port tables for Robin ; IF robin ; help text prhtbl: db cr,lf,'COMMUNICATIONS port' db cr,lf,'GENERAL purpose port' db cr,lf,'PRINTER port$' ; command table prttbl: db 03H ;Three entries db 0EH,'COMMUNICATIONS$' dw comptb db 07H,'GENERAL$' dw gppptb db 07H,'PRINTER$' dw prnptb ; port entry table ; table entries are: ; db iobyte-value, BDOS output function, hardware port address ; (control/status) ; ;At present, the hardware port address is only used for sending a break. comptb: db batio,punout,comtst gppptb: db gppio,conout,gentst prnptb: db lptio,conout,prntst prtadr: db comtst ;space for current hardware port address ENDIF;robin IF iobyt prtfun: db punout ;Function to use for output to comm port prtiob: db batio ;I/O byte to use for communicating coniob: db defio ;I/O byte to use for console ENDIF;iobyt IF NOT iobyt prttbl equ 0 ; SET PORT is not supported prhtbl equ 0 ENDIF;NOT iobyt ; ; ; Set up screen display for file transfer ; called with kermit version in DE ; sysscr: push d ; save version for a bit lxi d,outlin ; clear screen, position cursor call prtstr ; do it pop d ; get Kermit's version IF NOT (osi OR crt) ; got cursor control? call prtstr ; print it mvi e,'[' ; open bracket call outcon ; print it (close bracket is in outln2) lxi d,sysver ; get name and version of system module call prtstr lxi d,outln2 ; yes, print field names call prtstr lda dbgflg ; is debugging enabled? ora a rz ; finished if no debugging lxi d,outln3 ; set up debugging fields call prtstr ENDIF;NOT (osi OR crt) ret ; ; Calculate free space for current drive ; returns value in HL sysspc: IF cpm3 ;cpm3's alloc vect may be in another bank lda fcb ;If no drive, get ora a ; logged in drive jz dir180 dcr a ;FCB drive A=1 normalize to be A=0 jmp dir18a dir180: mvi c,rddrv call bdos dir 18a: mov e,a ;drive in e mvi c,getfs ;get free space BDOS funct call bdos ;returns free recs (3 bytes in buff..buff+2) mvi b,3 ;conv recs to K by 3 bit shift dir18b: xra a ;clear carry mvi c,3 ;for 3 bytes lxi h,buff+3 ;point to addr + 1 dir18c: dcx h ;point to less sig. byte mov a,m ;get byte rar ;carry -> A -> carry mov m,a ;put back byte dcr c ;for all bytes (carry not mod) jnz dir18c dcr b ;shift 1 bit 3 times jnz dir18b mov e,m ;get least sig byte inx h mov d,m ;get most sig byte xchg ;get K free in HL ENDIF;cpm3 IF NOT cpm3 ; the rest are CP/M 2.2 systems, so use the alloc vector mvi c,getalv ;Address of CP/M Allocation Vector call bdos xchg ;Get its length lhld bmax inx h lxi b,0 ;Initialize Block count to zero dir19: push d ;Save allocation address ldax d mvi e,8 ;set to process 8 blocks dir20: ral ;Test bit jc dir20a inx b dir20a: mov d,a ;Save bits dcx h mov a,l ora h jz dir21 ;Quit if out of blocks mov a,d ;Restore bits dcr e ;count down 8 bits jnz dir20 ;do another bit pop d ;Bump to next count of Allocation Vector inx d jmp dir19 ;process it dir21: pop d ;Clear Allocation vector from stack mov l,c ;Copy block to 'HL' mov h,b lda bshiftf ;Get Block Shift Factor sui 3 ;Convert from records to thousands rz ;Skip shifts if 1K blocks dir22: dad h ;Multiply blocks by 'K per Block' dcr a jnz dir22 ret ENDIF;NOT cpm3 [Toad Hall] ; ; ; selmdm - select modem port ; selcon - select console port ; selmdm is called before using inpmdm or outmdm; selcon is called before ; using inpcon or outcon. ; For iobyt systems, diddle the I/O byte to select console or comm port; ; For Decision I, switches Multi I/O board to console or modem serial ; port. [Toad Hall] ; For the rest, does nothing. ; preserves bc, de, hl. selmdm: IF iobyt lda prtiob ;Set up for output to go to the comm port sta iobyte ;Switch byte directly ENDIF;iobyt IF mdI lda group ori mdmgrp ;Mask modem serial port out grpsel ENDIF;mdI [Toad Hall] ret selcon: IF iobyt lda coniob ;Set up for output to go to the console port sta iobyte ;Switch directly ENDIF;iobyt IF mdI lda group ori congrp ;Mask console serial port (1) out grpsel ENDIF;mdI [Toad Hall] ret ; ; Get character from console, or return zero. ; result is returned in A. destroys bc, de, hl. ; inpcon: IF NOT iobyt mvi c,dconio ;Direct console I/O BDOS call. mvi e,0FFH ;Input. call BDOS ENDIF;NOT iobyt IF iobyt call bconst ;Get the status ora a ;Anything there? rz ;No, forget it call bconin ;Yes, get the character ENDIF;iobyt ret ; ; ; Output character in E to the console. ; destroys bc, de, hl ; outcon: IF NOT iobyt mvi c,dconio ;Console output bdos call. call bdos ;Output the char to the console. ENDIF;NOT iobyt IF iobyt mov c,e ;Character call bcnout ;to Console ENDIF;iobyt ret ; ; ; outmdm - output a char from E to the modem. ; the parity bit has been set as necessary. ; returns nonskip; bc, de, hl preserved. IF osi OR apple outmdm: push h lxi h,mnprts ;address of the port status register outmd2: mov a,m ; get port status in A ani output ;Loop till ready. jz outmd2 lxi h,mnport ;address of port data register mov m,e ; write the character pop h ret ENDIF;osi OR apple IF osbrn1 outmdm: call osldst ;Read the status port ani output ;Loop till ready. jz outmdm mov a,e jmp osstda ;Write to the data port ENDIF;osbrn1 IF inout outmdm: in mnprts ;Get the output done flag. ani output ;Is it set? jz outmdm ;If not, loop until it is. mov a,e out mnport ;Output it. ret ENDIF;inout IF iobyt ;****Note that we enter from outpkt with the I/O byte already set up for ;output to go to the comm port outmdm: push h push b lda prtfun ;Get the output function mov c,a ;Into C call bdos ;And output the character pop b pop h ret ENDIF;iobyt IF cpm3 outmdm: push h push b mvi c,auxout ;Output to the aux output device call bdos pop b pop h ret ENDIF;cpm3 ; ; ; get character from modem; return zero if none available. ; for IOBYT systems, the modem port has already been selected. ; destroys bc, de, hl. inpmdm: IF iobyt call bconst ;Is Char at COMM-Port? ora a ;something there? rz ; return if nothing there call bconin ; data present. read data. ENDIF;iobyt IF cpm3 mvi c,auxist call bdos ;is char at auxin? ora a ;something there? rz ;no mvi c,auxin call bdos ;read char from auxin ENDIF;cpm3 IF osi OR apple lda mnprts ;Get the port status into A. ani input ;See if the input ready bit is on. rz ;If not then return. lda mnport ;If so, get the char. ENDIF;osi OR apple IF osbrn1 call osldst ;Read the status port ani input ;Something there? rz ;Nope call osldda ;Read the data port ENDIF;osbrn1 IF inout ;Note: modem port should already be selected for mdI. [Toad Hall] in mnprts ;Get the port status int o A. ani input ;See if the input ready bit is on. rz ;If not then return. in mnport ;If so, get the char. ENDIF;inout ret ; return with character in A ; ; ; outlpt - output character in E to printer ; console is selected. ; preserves de. outlpt: IF NOT iobyt mvi c,lstout call bdos ;Char to printer ENDIF;NOT iobyt IF iobyt push d mov c,e call blsout pop d ENDIF;iobyt ; ; ; Screen manipulation routines ; csrpos - move to row B, column C ; ; csrpos for terminals that use a leadin sequence followed ; by (row + 31.) and (column + 31.) ; IF NOT (robin OR dmII OR vt100 OR osi OR crt OR vector) csrpos: push b ; save coordinates lxi d,curldn ; get cursor leadin sequence call prtstr ; print it pop h ; restore coordinates mov a,h ; get row adi (' '-1) ; space is row one mov e,a push h call outcon ; output row pop h mov a,l ; get column adi (' '-1) ; space is column one mov e,a jmp outcon ; output it and return ENDIF;NOT (robin OR dmII OR vt100 OR osi OR crt OR vector) ; ; csrpos for ANSI terminals ; IF robin OR dmII OR vt100 csrpos: push b ; save coordinates lxi d,curldn ; get cursor leadin sequence call prtstr ; print it pop h ; peek at coordinates push h ; then save away again mov l,h ; l = row mvi h,0 ; hl = row call nout ; output in decimal mvi e,';' ; follow with semicolon call outcon ; print it pop h ; restore column mvi h,0 ; hl = column call nout mvi e,'H' ; terminate with 'move cursor' command jmp outcon ; output it and return ENDIF;robin OR dmII OR vt100 ; ; csrpos for the Vector General. It's weird. ; IF vector csrpos: dcr b ; vector uses zero-based addressing? dcr c push b ; save coordinates mvi e,esc ; print an escape call outcon pop d ; peek at coordinates push d call outcon ; output column pop d mov e,d ; get row jmp outcon ; output and return ENDIF;vector IF osi OR crt ; systems without cursor positioning csrpos: ret ; dummy routine referenced by linkage section ENDIF;osi OR crt ; ; position to various fields: ; for the Kermits with cursor positioning, the display looks like this: ; 5 10 15 20 25 30 35 ; +----|----|----|----|----|----|----|... ; 1 | ; 2 | Kermit-80 v4.0 [system] ; 3 | ; 4 |Number of packets: ____ ; 5 |Number of retries: ____ ; 6 |File name: ____________ ; 7 |... ; 8 |... ; 9 |RPack: ___(if debugging)... ; 10 | ; 11 |SPack: ___(if debugging)... ; 12 | ; 13 |Kermit-80 A:> (when finished) ; IF NOT (osi OR crt) scrnp: lxi b,4*100H+20 jmp csrpos scrnrt: lxi b,5*100H+20 jmp csrpos scrfln: lxi b,6*100H+12 call csrpos clreol: lxi d,tk jmp prtstr screrr: lxi b,7*100H+1 call csrpos jmp clreol scrst: lxi b,8*100H+1 call csrpos jmp clreol rppos: lxi b,9*100H+8 call csrpos jmp clreol sppos: lxi b,11*100H+8 call csrpos jmp clreol scrend: lxi b,13*100H+1 call csrpos clreos: lxi d,tj jmp prtstr ENDIF;NOT (osi OR crt) IF osi OR crt ; no cursor control scrnp: mvi e,' ' jmp outcon scrnrt: mvi e,' ' call outcon mvi e,'%' jmp outcon scrfln: screrr: scrst: scrend: jmp prcrlf ;Print CR/LF [Toad Hall] rppos: lxi d,prpack jmp prtstr sppos: lxi d,pspack jmp prtstr ENDIF;osi OR crt ; ; delchr - make delete look like a backspace. Unless delete is a printing ; character, we just need to print a backspace. (we'll output clrspc ; afterwards) ; For Kaypro and Vector General, delete puts a blotch on the screen. ; For Apple and Osborne 1, delete moves but doesn't print. delchr: IF kpII OR vector OR apple OR osbrn1 lxi d,delstr jmp prtstr ENDIF;kpII OR vector OR apple OR osbrn1 IF NOT (kpII OR vector OR apple OR osbrn1) mvi e,bs ;get a backspace jmp outcon ENDIF;NOT (kpII OR vector OR apple OR osbrn1) ; erase the character at the current cursor position clrspc: mvi e,' ' call outcon mvi e,bs ;get a backspace jmp outcon ; erase the current line clrlin: lxi d,eralin jmp prtstr ; erase the whole screen, and go home. preserves b (but not c) clrtop: lxi d,erascr jmp prtstr ; Some frequently-used routines (duplicates of those in CP4MIT): ; prcrlf - output a CR/LF ; prtstr - output string in DE ; rskp - return, skipping over error return prcrlf: lxi d,crlf prtstr: mvi c,prstr jmp bdos rskp: pop h ; Get the return address inx h ; Increment by three inx h inx h pchl ; Copy block of data ; source in HL, destination in DE, byte count in BC ; called by: cp4sys, mfname ; mover: IF NOT z80 ; 8080's have to do it the hard way mov a,m stax d inx h inx d dcx b mov a,b ora c jnz mover ENDIF;NOT z80 IF z80 db 0EDh,0B0h ; Z80 LDIR instruction ENDIF;z80 ret ; ; ; Miscellaneous messages ; crlf: db cr,lf,'$' cfgmsg: db 'configured for $' IF adm3a OR tvi925 OR vt52 OR vt100 witmsg: db ' with $' ENDIF;adm3a OR tvi925 OR vt52 OR vt100 ;**************************Terminal tables******************* ********* IF NOT (osi OR crt) ; got cursor control? outln2: db ']',cr,lf,cr,lf,'Number of packets:' db cr,lf,'Number of retries:' db cr,lf,'File name:$' outln3: db cr,lf,cr,lf ; debugging messages db cr,lf,'RPack:' db cr,lf ; blank line in case of long packet db cr,lf,'SPack:$' ENDIF;NOT (osi OR crt) IF brain sysver: db 'Intertec SuperBrain$' outlin: db ('A'-100O),esc,'~k',cr,lf,tab,tab,'$' erascr: db ('A'-100O),esc,'~k$' ;Clear screen and go home. eralin: db cr,esc,'~K$' ;Clear line. curldn: db esc,'Y$' ; leadin for cursor positioning ttab: ;Table start location. ta: db ('K'-100O),'$',0,0 ;Cursor up. tb: db 12O,'$',0,0 ;Cursor down. tc: db ('F'-100O),'$',0,0 ;Cursor right. td: db '$',0,0,0 ;(can't) Cursor left te: db '$',0,0,0 ;(can't) Clear display tf: db '$',0,0,0 ;(can't) Enter graphics mode tg: db '$',0,0,0 ;(can't) Exit graphics mode th: db ('A'-100O),'$',0,0 ;Cursor home. ti: db ('K'-100O),'$',0,0 ;Reverse linefeed. tj: db esc,'~k$',0 ;Clear to end of screen. tk: db esc,'~K$',0 ;Clear to end of line. ENDIF;brain ; IF osbrn1 sysver: db 'Osborne 1$' outlin: db 1AH,tab,'$' ;(Clear screen, home cursor) erascr: db 1AH,'$' ;Clear screen and go home. eralin: db cr,esc,'T$' ;Clear line. delstr: db bs,bs,'$' ; Adjust for delete curldn: db esc,'=$' ;Cursor lead-in ttab: ;Table start location. ta: db ('K'-100O),'$',0,0 ;Cursor up. tb: db 12O,'$',0,0 ;Cursor down. tc: db ('L'-100O),'$',0,0 ;Cursor right. td: db bs,'$',0,0 ;Cursor left. te: db subt,'$',0,0 ;Clear screen. tf: db '$',0,0,0 ;(can't) Enter graphics mode tg: db '$',0,0,0 ;(can't) Exit graphics mode th: db ('^'-100O),'$',0,0 ;Cursor home. ti: db ('K'-100O),'$',0,0 ;Reverse linefeed. tj: db esc,'T$',0 ;(can't) Clear to end of screen. tk: db esc,'T$',0 ;Clear to end of line. ENDIF;osbrn1 ; IF apple sysver: db 'Apple II CP/M$' outlin: db ('^'-100O),esc,'Y',cr,lf,' $' erascr: db ('^'-100O),esc,'Y$' ;Clear screen and go home. eralin: db cr,esc,'T$' ;Clear line. delstr: db bs,bs,'$' ; Adjust for delete curldn: db esc,'=$' ;Cursor lead-in ttab: ;Table start location. ta: db ('K'-100O),'$',0,0 ;Cursor up. tb: db 12O,'$',0,0 ;Cursor down. tc: db ('F'-100O),'$',0,0 ;Cursor right. td: db '$',0,0,0 ;(can't) Cursor left te: db '$',0,0,0 ;(can't) Clear display tf: db '$',0,0,0 ;(can't) Enter graphics mode tg: db '$',0,0,0 ;(can't) Exit graphics mode th: db ('^'-100O),'$',0,0 ;Cursor home. ti: db ('K'-100O),'$',0,0 ;Reverse linefeed. tj: db esc,'Y$',0 ;Clear to end of screen. tk: db esc,'T$',0 ;Clear to end of line. ENDIF;apple ; IF vector sysver: db 'Vector Graphics$' outlin: db ('D'-100O),cr,lf,tab,tab,'$' erascr: db ('D'-100O),'$' ;Clear screen and go home. eralin: db cr,('Q'-100O),'$' ;Clear line. delstr: db bs,' ',bs,bs,'$' ; adjust for echoing delete character ttab: ;Table start location. ta: db ('U'-100O),'$',0,0 ;Cursor up. tb: db 12O,'$',0,0 ;Cursor down. tc: db ('Z'-100O),'$',0,0 ;Cursor right. td: db '$',0,0,0 ;(can't) Cursor left te: db '$',0,0,0 ;(can't) Clear display tf: db '$',0,0,0 ;(can't) Enter graphics mode tg: db '$',0,0,0 ;(can't) Exit graphics mode th: db ('B'-100O),'$',0,0 ;Cursor home. ti: db ('U'-100O),'$',0,0 ;Reverse linefeed. tj: db ('P'-100O),'$',0,0 ;Clear to end of screen. tk: db ('Q'-100O),'$',0,0 ;Clear to end of line. ENDIF;vector ; IF telcon sysver: db 'Telcon Zorba$' ENDIF;telcon IF heath sysver: db 'Heath/Zenith 89$' ENDIF;heath IF z100 sysver: db 'Heath/Zenith Z-100 CP/M$' ENDIF;z100 IF vt52 ; DEC VT52 ttytyp: db 'VT52$' ENDIF;vt52 IF heath OR z100 OR telcon OR vt52 outlin: db esc,'H',esc,'J',cr,lf,tab,tab,'$' erascr: db esc,'H',esc,'J$' ;Clear screen and go home. eralin: db cr,esc,'K$' ;Clear line. curldn: db esc,'Y$' ;cursor leadin ttab: ;Table start location. ta: db esc,'A$',0 ;Cursor up. tb: db esc,'B$',0 ;Cursor down. tc: db esc,'C$',0 ;Cursor right. td: db esc,'D$',0 ;Cursor left te: db esc,'E$',0 ;Clear display tf: db esc,'F$',0  ;Enter Graphics Mode tg: db esc,'G$',0 ;Exit Graphics mode th: db esc,'H$',0 ;Cursor home. ti: db esc,'I$',0 ;Reverse linefeed. tj: db esc,'J$',0 ;Clear to end of screen. tk: db esc,'K$',0 ;Clear to end of line. ENDIF;heath OR z100 OR telcon OR vt52 ; IF trs80lb sysver: db 'TRS-80 II Lifeboat CP/M$' outlin: db esc,':',cr,lf,tab,tab,'$' erascr: db esc,':$' ;Clear screen and go home. eralin: db cr,esc,'T$' ;Clear line. curldn: db esc,'=$' ;Cursor lead-in ttab: ;Table start location. ta: db 0BH,'$',0,0 ;Cursor up. tb: db 0AH,'$',0,0 ;Cursor down. tc: db 0CH,'$',0,0 ;Cursor right. td: db bs,'$',0,0 ;Cursor left te: db esc,':$',0 ;Clear display tf: db '$',0,0,0 ;(can't) Enter Graphics Mode tg: db '$',0,0,0 ;(can't) Exit Graphics mode th: db 1EH,'$',0,0 ;Cursor home. ti: db 0BH,'$',0,0 ;Reverse linefeed. tj: db esc,'Y$',0 ;Clear to end of screen. tk: db esc,'T$',0 ;Clear to end of line. ENDIF;trs80lb ; IF trs80pt sysver: db 'TRS-80 II P+T CP/M$' outlin: db 0CH ,cr,lf,tab,tab,'$' erascr: db 0CH,'$' ;Clear screen and go home. eralin: db cr,01H,'$' ;Clear line. curldn: db esc,'Y$' ;Cursor lead-in ttab: ;Table start location ;Must be 4 bytes each ta: db 1EH,'$',0,0 ;Cursor up. tb: db 1FH,'$',0,0 ;Cursor down. tc: db 1DH,'$',0,0 ;Cursor right. td: db 1CH,'$',0,0 ;Cursor left te: db 0CH,'$',0,0 ;Clear display tf: db 11H,'$',0,0 ;Enter Graphics Mode tg: db 14H,'$',0,0 ;Exit Graphics mode th: db 06H,'$',0,0 ;Cursor home. ti: db 1EH,'$',0,0 ;Reverse linefeed. tj: db 02H,'$',0,0 ;Clear to end of screen. tk: db 01H,'$',0,0 ;Clear to end of line. ENDIF;trs80pt ; IF robin sysver: db 'VT180 "Robin"$' ENDIF;robin IF dmII sysver: db 'DECmate II CP/M-80$' ENDIF;dmII IF vt100 ttytyp: db 'VT100$' ENDIF;vt100 IF robin OR dmII or vt100 ; Note that we cannot support Graphics Mode or the H19 erase-screen command ; (E), because the sequences are more than three bytes. outlin: db esc,3CH,esc,'[H',esc,'[J',cr,lf,tab,tab,'$' erascr: db esc,'[H',esc,'[J$' ;Clear screen and go home. eralin: db cr,esc,'[K$' ;Clear line. curldn: db esc,'[$' ; Cursor leadin ttab: ta: db esc,'[A$' ; Cursor up. tb: db esc,'[B$' ; Cursor down. tc: db esc,'[C$' ; Cursor right. td: db esc,'[D$' ; Cursor left te: db '$',0,0,0 ; (can't) Clear display tf: db '$',0,0,0 ; (don't) Enter Graphics Mode tg: db '$',0,0,0 ; (don't) Exit Graphics mode th: db esc,'[H$' ; Cursor home. ti: db esc,'M$',0 ; Reverse linefeed. tj: db esc,'[J$' ; Clear to end of screen. tk: db esc,'[K$' ; Clear to end of line. ENDIF;robin OR dmII or vt100 ; IF kpii sysver: db 'Kaypro II$' outlin: db subt,cr,lf,tab,tab,'$' erascr: db subt,'$' ;Clear screen and home. eralin: db cr,18H,'$' ;Clear line. curldn: db esc,'=$' ;Cursor lead-in delstr: db bs,' ',bs,bs,'$' ; adjust for echoing delete character ttab: ;Table start location. ta: db 0BH,'$',0,0 ;Cursor up. tb: db 0AH,'$',0,0 ;Cursor down. tc: db 0CH,'$',0,0 ;Cursor right. td: db bs,'$',0,0 ;Cursor left te: db subt,'$',0,0 ;Clear display tf: db esc,'G$',0 ; Enter Graphics Mode (select Greek) tg: db esc,'A$',0 ; Exit Graphics mode (select ASCII) th: db 1EH,'$',0,0 ; Cursor home. [UTK016] ti: db esc,'E','$',0 ; Reverse linefeed. (insert line) tj: db 'W'-100O,'$',0,0 ; Clear to end of screen. tk: db 'X'-100O,'$',0,0 ; Clear to end of line. ENDIF ; kpii ; IF mikko sysver: db 'MikroMikko$' outlin: db subt,cr,lf,tab,'$' erascr: db subt,'$' ;Clear screen and go home. eralin: db cr,1CH,'$' ;Clear line. curldn: db esc,'=$' ;cursor leadin ttab: ;Table start location. ta: db 0BH,'$',0,0 ;Cursor up. tb: db 0AH,'$',0,0 ;Cursor down. tc: db 0CH,'$',0,0 ;Cursor right. td: db bs,'$',0,0 ;Cursor left te: db subt,'$',0,0 ;Clear display tf: db '$',0,0,0 ;(can't) Enter Graphics Mode tg: db '$',0,0,0 ;(can't) Exit Graphics mode th: db 1EH,'$',0,0 ;Cursor home. ti: db '$',0,0,0 ;(can't) Reverse linefeed. tj: db 1cH,'$',0,0 ;Clear to end of screen. tk: db 1cH,'$',0,0 ;Clear to end of line. ENDIF;mikko ; IF gener or cpm3 sysver: db 'Generic CP/M-80$' ENDIF;gener or cpm3 IF bbII sysver: db 'Big Board II$' ENDIF;bbII IF mdI sysver: db 'Morrow Decision I$' ENDIF;mdI [Toad Hall] IF mmdI sysver: db 'MicroDecision I$' ENDIF;mmdI IF osi sysver: db 'Ohio Scientific$' ENDIF;osi IF osi OR crt outlin: db cr,lf,'Starting ...$' erascr equ crlf ;"Home & clear" (best we can do). eralin: db '^U',cr,lf,'$' ;Clear line. prpack: db cr,lf,'RPack: $' pspack: db cr,lf,'SPack: $' ttab equ 0 ; no VT52 table ENDIF;osi OR crt IF tvi925 ;(incidentally, works fine for Freedom 100 also [Toad Hall]) ;adm3a entry and tvi925 entry separated to remove warning message. ttytyp: db 'TVI925$' outlin: db 'Z'-64,0,0,cr,lf,'$' erascr: db 'Z'-64,0,0,'$' ;Clear screen and home eralin: db esc,'Y$',0 ;Clear to end of sreen curldn: db cr,esc,'=$' ;Cursor lead-in ttab: ;Table start location ;(MUST be 4 bytes each) ta: db 'K'-64,'$',0,0 ;Cursor up, stop at top tb: db 'V'-64,'$',0,0 ;Cursor down, stop at bottom tc: db 'L'-64,'$',0,0 ;Cursor right, stop at right td: db 'H'-64,'$',0,0 ;Cursor left, stop at left te: db 'Z'-64,0,0,'$' ;Clear display (2 pad nulls) tf: db '$',0,0,0 ;(can't) Enter Graphics mode tg: db '$',0,0,0 ;(can't) Exit Graphics mode th: db 1EH,'$',0,0 ;Cursor home ti: db esc,'j$',0 ;Reverse linefeed, scroll tj: db esc,'Y$',0 ;Clear to end of sreen tk: db esc,'T$',0 ;Clear to end of line ENDIF;tvi925 IF adm3a ttytyp: db 'ADM3A$' outlin: db 'Z'-64,0,0,cr,lf,'$' erascr: db 'Z'-64,0,0,'$' ;Clear screen and home eralin: db esc,'Y$',0 ;Clear to end of sreen curldn: db cr,esc,'=$' ;Cursor lead-in ttab: ;Table start location ;(MUST be 4 bytes each) ta: db 'K'-64,'$',0,0 ;Cursor up, stop at top tb: db 'J'-64,'$',0,0 ;Cursor down CTRL-J tc: db 'L'-64,'$',0,0 ;Cursor right, stop at right td: db 'H'-64,'$',0,0 ;Cursor left, stop at left te: db 'Z'-64,0,0,'$' ;Clear display (2 pad nulls) tf: db '$',0,0,0 ;(can't) Enter G raphics mode tg: db '$',0,0,0 ;(can't) Exit Graphics mode th: db 1EH,'$',0,0 ;Cursor home ti: db 'K'-64,'$',0,0 ;Reverse linefeed tj: db '$',0,0,0 ;(can't) Clear to end of screen tk: db '$',0,0,0 ;(can't) Clear to end of line ENDIF;adm3a END ',0,0 ;Cursor up. tb: db 12O,'$',0,0 ;Cursor down. tc: db ('L'-100O),'$',0,0 ;Cursor right. td: db bs,'$',0,0 ;Cursor left. te: db subt,'$',0,0 ;Clear screen. tf: db '$',0,0,0 ;(can't) Enter graphics mode tg: db '$',0,0,0 ;(can't) Exit graphics mode th: db ('^'-100O),'$',0,0 ;Cursor home. ti: db ('K'-100O),'$',0,0 ;Reverse linefeed. tj: db esc,'T$',0 ;(can't) Clear to end of screen. tk: db esc,'T$',0 ;Clear to end of line. ENDIF;osbrn1 ; IF apple sysver: db 'Apple II CP/M$' outlin: db ('^'-100O),esc,'Y',cr,lf,' $' erascr: db ('^'-100O),esc,'Y$' ;Clear screen and go home. eralin: db cr,esc,'T$' ;Clear line.; CP4LNK.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This file describes the areas used to communicate between KERMIT ; and the customizing overlay. It is included by the overlay. ; This file should be changed only to reflect changes in the ; system-independent portion of Kermit (enhancements, I hope). ; ; revision history: ; edit 3: August 3, 1984 (CJC) ; put "mover" in CP4SYS, so we can do a Z80 block move if so inclined. ; ; edit 2: July 10, 1984 (CJC) ; integrate Toad Hall changes for LASM compatibility: CP4LNK is linked ; by CP4DEF, and links CP4SYS. ; ; edit 1: May, 1984 (CJC) ; extracted from CPMBASE.M80 version 3.9; modifications are described ; in the accompanying .UPD file. ; ; Define the entry section. These addresses contain jumps to ; useful routines in KERMIT. To show we know what we're doing, ; we store the length of this section (entsiz) in our linkage ; section. I didn't use ORG and DS because I don't want zeroes ; generated for all the space between here and the actual start ; of cp4sys. kermit equ 103H ; reentry address nout equ 106H ; output HL in decimal entsiz equ 2*3 ; 2 entries, so far. ; ; End of entry section. ; ; Linkage section. This block (through the definition of lnksiz) ; is used by Kermit to reach the routines and data in the overlay. ; The section length is stored at the beginning of the overlay ; area so Kermit can verify that the overlay section is (a) present, ; (b) in the right place, and (c) the same size as (and therefore ; presumably the same as) the linkage section Kermit is expecting. ; ASEG ORG OVLADR ; lnkflg: dw lnksiz ; linkage information for consistency check. dw entsiz ; length of entry table, for same. db 0 ; overlay ID (or something) db 1 ; overlay revision level ; ; hooks for system-dependent routines: ; ; Input/output routines. ; jmp selmdm ; select modem for I/O jmp outmdm ; output character in E to modem jmp inpmdm ; read character from modem. return character or 0 in A. jmp selcon ; select console for I/O jmp outcon ; output character in E to console jmp inpcon ; read char from console. return character or 0 in A jmp outlpt ; output character in E to printer ; ; screen formatting routines jmp clrlin ; erase current line jmp clrspc ; erase current position (after backspace) jmp delchr ; make delete look like backspace jmp clrtop ; erase screen and go home ; ; these routines are called to display a field on the screen. jmp scrend ; move to prompt field jmp screrr ; move to error message field jmp sc rfln ; move to filename field jmp scrnp ; move to packet count field jmp scrnrt ; move to retry count field jmp scrst ; move to status field jmp rppos ; move to receive packet field (debug) jmp sppos ; move to send packet field (debug) ; jmp sysinit ; program initialization jmp sysexit ; program termination jmp syscon ; remote session initialization jmp syscls ; return to local command level jmp sysinh ; help text for interrupt (escape) extensions jmp sysint ; interrupt (escape) extensions, including break jmp sysflt ; filter for incoming characters. ; called with character in E. jmp sysbye ; terminate remote session jmp sysspd ; baud rate change routine. ; called with value from table in DE jmp sysprt ; port change routine. ; called with value from table in DE jmp sysscr ; screen setup for file transfer ; called with Kermit's version string in DE jmp csrpos ; move cursor to row B, column C jmp sysspc ; calculate free space for current drive jmp mover ; do block move ; ; Local parameter values ; pttab: dw ttab ; points to local equivalents to VT52 escape sequences spdtab: dw spdtbl ; address of baud rate command table, or zero spdhlp: dw sphtbl ; address of baud rate help table, or zero prttab: dw prttbl ; address of port command table, or zero prthlp: dw prhtbl ; address of port help table, or zero timout: dw fuzval ; Fuzzy timeout. vtflg: db vtval ; VT52 emulation flag escchr: db defesc ; Storage for the escape character. speed: dw 0FFFFH ; storage for the baud rate (initially unknown) dbgflg: db 0 ; debugging flag ecoflg: db 0 ; Local echo flag (default off). flwflg: db 1 ; File warning flag (default on). ibmflg: db 0 ; IBM flag (default off). cpmflg: db 0 ;[bt] file-mode flag (default is DEFAULT) parity: db defpar ; Parity. spsiz: db dspsiz ; Send packet size. rpsiz: db drpsiz ; Receive packet size. stime: db dstime ; Send time out. rtime: db drtime ; Receive time out. spad: db dspad ; Send padding. rpad: db drpad ; Receive padding. spadch: db dspadc ; Send padding char. rpadch: db drpadc ; Receive padding char. seol: db dseol ; Send EOL char. reol: db dreol ; Receive EOL char. squote: db dsquot ; Send quote char. rquote: db drquot ; Receive quote char. chktyp: db dschkt ; Checksum type desired tacflg: db tac AND 0FFH ; TACtrap status (zero = off, nonzero = on; ; when non-zero, is current TAC intercept character) tacchr: db tacval ; Desired TAC intercept character (even when off) ; space used by directory command; here because space calculation is ; (operating) system-dependent bmax: ds 2 ; highest block number on drive bmask: ds 1 ; (records/block)-1 bshiftf: ds 1 ; number of shifts to multiply by rec/block nnams: ds 1 ; counter for filenames per line lnksiz equ $-lnkflg ; length of linkage section, for consistency check. IF lasm ; If we're assembling with LASM, LINK CP4SYS ; get the next section. ENDIF;lasm ; CP4CMD.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This file provides a user oriented way of parsing commands. ; It is similar to that of the COMND JSYS in TOPS-20. ; ; revision history (latest first): ; edit 3: July 8, 1984 (CJC) ; integrate Toad Hall changes for LASM compatibility: CP4CPM is linked ; by CP4WLD, and links CP4UTL. ; ; edit 2: June 5, 1984 (CJC) ; formatting and documentation; delete unnecessary code at cminb7; add ; module version string. ; ; edit 1: May, 1984 (CJC) ; extracted from CPMBASE.M80 version 3.9; modifications are described in ; the accompanying .UPD file. cmdver: db 'CP4CMD.ASM (3) 8-Jul-84$' ; name, edit number, date ; This routine prints the prompt in DE and specifies the reparse ; address. ; called by: kermit prompt: pop h ;Get the return address. push h ;Put it on the stack again. shld cmrprs ;Save it as the address to go to on reparse. lxi h,0 ;Clear out hl pair. dad sp ;Get the present stack pointer. shld cmostp ;Save for later restoral. xchg ;Save the pointer to the prompt. shld cmprmp xchg lxi h,cmdbuf shld cmcptr ;Initialize the command pointer. shld cmdptr xra a sta cmaflg ;Zero the flags. sta cmccnt mvi a,0FFH ;Try it this way (Daphne.) sta cmsflg call prcrlf ;Print a CR/LF [Toad Hall] jmp prprmp ;Print the prompt. [Toad Hall] ; ; This address is jumped to on reparse. ; here from: cmcfrm, cmkeyw, cmifil, cminbf repars: lhld cmostp ;Get the old stack pointer. sphl ;Make it the present one. lxi h,cmdbuf s hld cmdptr mvi a,0FFH ;Try it this way (Daphne.) sta cmsflg lhld cmrprs ;Get the reparse address. pchl ;Go there. ; This address can be jumped to on a parsing error. ; here from: cmkeyw, cminbf prserr: lhld cmostp ;Get the old stack pointer. sphl ;Make it the present one. lxi h,cmdbuf shld cmcptr ;Initialize the command pointer. shld cmdptr xra a sta cmaflg ;Zero the flags. sta cmccnt mvi a,0FFH ;Try it this way (Daphne.) sta cmsflg call prcrlf ;Print a CR/LF [Toad Hall] call prprmp ;Print the prompt [Toad Hall] ;* Instead return to before the prompt call. lhld cmrprs pchl ; ; This routine parses the specified function in A. Any additional ; information is in DE and HL. ; Returns +1 on success ; +4 on failure (assumes a JMP follows the call) ; called by: log, setcom, read, send, xmit, dir, era, keycmd, cfmcmd comnd: sta cmstat ;Save what we are presently parsing. call cminbf ;Get chars until an action or a erase char. cpi cmcfm ;Parse a confirm? jz cmcfrm ;Go get one. cpi cmkey ;Parse a keyword? jz cmkeyw ;Try and get one. cpi cmifi ;Parse an input file spec? jz cmifil ;Go get one. cpi cmifin ;Input file-spec silent? jz cmifil ;do as he wishes cpi cmofi ;Output file spec? jz cmofil ;Go get one. cpi cmtxt ;Parse arbitrary text? jz cmtext ;Go do it. lxi d,cmer00 ;"?Unrecognized COMND call" call prtstr ret ; ; This routine parses arbitrary text up to a CR. ; Accepts DE: address to put text ; Returns in A: number of chars in text (may be 0) ; DE: updated pointer ; called by: comnd cmtext: xchg ;Put the pointer to the dest in HL. shld cmptab ;Save the pointer. mvi b,0 ;Init the char count cmtxt1: call cmgtch ;Get a char. ora a ;Terminator? jp cmtxt5 ;No, put in user space. ani 7FH ;Turn off minus bit. cpi esc ;An escape? jnz cmtxt2 ;No. mvi c,conout mvi e,bell ;Get a bell. call bdos xra a sta cmaflg ;Turn off the action flag. lhld cmcptr ;Move the pointer to before the escape. dcx h shld cmcptr shld cmdptr lxi h,cmccnt ;Get the char count. dcr m ;Decrement it by one. jmp cmtxt1 ;Try again. cmtxt2: cpi '?' ;Is it a question mark? jz cmtxt3 ;If so put it in the text. cpi ff ;Is it a formfeed? cz clrtop ;If so blank the screen. mov a,b ;Return the count. lhld cmptab ;Return updated pointer in HL. xchg jmp rskp ;Return success. cmtxt3: lxi h,cmaflg ;Point to the action flag. mvi m,0 ;Set it to zero. cmtxt5: inr b ;Increment the count. lhld cmptab ;Get the pointer. mov m,a ;Put the char in the array. inx h shld cmptab ;Save the updated pointer. jmp cmtxt1 ;Get another char. ; ; This routine gets a confirm. ; called by: comnd cmcfrm: call cmgtch ;Get a char. ora a ;Is it negative (a terminator;a space or ;a tab will not be returned here as they ;will be seen as leading white space.) rp ;If not, return failure. ani 7FH ;Turn off the minus bit. cpi esc ;Is it an escape? jnz cmcfr2 mvi c,conout mvi e,bell ;Get a bell. call bdos xra a sta cmaflg ;Turn off the action flag. lhld cmcptr ;Move the pointer to before the escape. dcx h shld cmcptr shld cmdptr lxi h,cmccnt ;Get the char count. dcr m ;Decrement it by one. jmp cmcfrm ;Try again. cmcfr2: cpi '?' ;Curious? jnz cmcfr3 lxi d,cmin00 ;Print something useful. call prtstr call prcrlf ;Print a crlf. [Toad Hall] call prprmp ;Reprint the prompt [Toad Hall] lhld cmdptr ;Get the pointer into the buffer. mvi a,'$' ;Put a $ there for printing. mov m,a lhld cmcptr dcx h ;Decrement and save the buffer pointer. shld cmcptr lxi d,cmdbuf call prtstr xra a ;Turn off the action flag. sta cmaflg jmp repars ;Reparse everything. cmcfr3: cpi ff ;Is it a form feed? cz clrtop ;If so blank the screen. jmp rskp ; ; This routine parses a keyword from the table pointed ; to in DE. The format of the table is as follows: ; ; addr: db n ;Where n is the # of entries in the table. ; db m ;M is the size of the keyword. ; db 'string$' ;Where string is the keyword. ; db a,b ;Where a & b are pieces of data ; ;to be returned. (Must be two of them.) ; ; The keywords must be in alphabetical order. ;**** Note: The data value a is returned in registers A and E. The ;**** data value b is returned in register D. This allows the two data ; bytes to be stored as: ; dw xxx ; and result in a correctly formatted 16-bit value in register pair ; DE. ; called by: comnd cmkeyw: shld cmhlp ;Save the help. xchg ;Get the address of the table. shld cmptab ;Save the beginning of keyword tab for '?'. mov b,m ;Get the number of entries in the table. inx h shld cmkptr lhld cmdptr ;Save the command pointer. shld cmsptr cmkey2: mov a,b ;Get the number of entries left. ora a ;Any left? rz ;If not we failed. lhld cmkptr mov e,m ;Get the length of the keyword. inx h cmkey3: dcr e ;Decrement the number of chars left. mov a,e cpi 0FFH ; Have we passed the end? jm cmkey5 ;If so go to the next. call cmgtch ;Get a char. ora a ;Is it a terminator? jp cmkey4 ;If positive, it is not. ani 7FH ;Turn off the minus bit. cpi '?' jnz cmky31 xra a sta cmaflg ;Turn off the action flag. lxi h,cmccnt ;Decrement the char count. dcr m ;* Must go through the keyword table and print them. lhld cmhlp ;For now print the help text. xchg call prtstr call prcrlf ;Print a crlf [Toad Hall] call prprmp ;Reprint the prompt [Toad Hall] lhld cmdptr ;Get the pointer into the buffer. mvi a,'$' ;Put a $ there for printing. mov m,a lhld cmcptr dcx h ;Decrement and save the buffer pointer. shld cmcptr lxi d,cmdbuf call prtstr jmp repars ;Reparse everything. cmky31: cpi esc ;Is it an escape? jnz cmky35 xra a sta cmaflg ;Turn off the action flag. push d push b push h call cmambg jmp cmky32 ;Not ambiguous. mvi c,conout mvi e,bell call bdos ;Ring the bell. lhld cmcptr ;Move the pointer to before the escape. dcx h shld cmcptr shld cmdptr lxi h,cmccnt ;Get the char count. dcr m ;Decrement it by one. pop h pop b pop d inr e ;Increment the left to parse char count. jmp cmkey3 cmky32: lhld cmcptr ;Pointer into buffer. dcx h ;Backup to the escape. xchg pop h push h cmky33: mov a,m ;Get the next char. cpi '$' ;Finished? jz cmky34 inx h xchg mov m,a ;Move it into the buffer. inx h xchg lda cmccnt ;Increment the char count. inr a sta cmccnt jmp cmky33 cmky34: lda cmccnt ;Get the character count. inr a ;Increment and save it. sta cmccnt xchg ;Put the command buffer pointer in HL. mvi a,' ' ;Get a blank. mov m,a ;Put it in the command buffer. inx h ;Increment the pointer shld cmcptr ;Save the updated pointer. shld cmdptr pop h push h xchg call prtstr ;Print the rest of the keyword. mvi c,conout mvi e,' ' call bdos ;Print a blank. pop h pop b pop d jmp cmky37 cmky35: push h push d call cmambg jmp cmky36 lxi d,cmer01 call prtstr ;Say its ambiguous. jmp prserr ;Give up. cmky36: pop d pop h cmky37: inr e ;Add one incase it is negative. mvi d,0 dad d ;Increment past the keyword. inx h ;Past the $. mov e,m ;Get the data. inx h mov d,m mov a,e jmp rskp cmkey4: cpi 'a' ;Is it less than a? jm cmky41 ;If so don't capitalize it. cpi 'z'+1 ;Is it more than z? jp cmky41 ;If so don't capitalize it. ani 137O ;Capitalize it. cmky41: mov d,m ;Get the next char of the keyword. inx h cmp d ;Match? jz cmkey3 ;If so get the next letter. cmkey5: mvi d,0 mov a,e ;Get the number of chars left. ora a ;Is it negative? jp cmky51 mvi d,0FFH ;If so, sign extend. cmky51: dad d ;Increment past the keyword. lxi d,0003H ;Plus the $ and data. dad d shld cmkptr dcr b ;Decrement the number of entries left. lhld cmsptr ;Get the old cmdptr. shld cmdptr ;Restore it. ;* check so we don't pass it. jmp cmkey2 ;Go check the next keyword. ; ; Test keyword for ambiguity. ; returns: nonskip if ambiguous, skip if OK. ; called by: cmkeyw cmambg: dcr b ;Decrement the number of entries left. rm ;If none left then it is not ambiguous. inr e ;This is off by one;adjust. mov c,e ;Save the char count. mov a,e ora a ;Any chars left? rz ;No, it can't be ambiguous. mvi d,0 dad d ;Increment past the keyword. mvi e,3 ;Plus the $ and data. dad d mov b,m ;Get the length of the keyword. inx h xchg lhld cmkptr ;Get pointer to keyword entry. mov a,m ;Get the length of the keyword. sub c ;Subtract how many left. mov c,a ;Save the count. cmp b jz cmamb0 rp ;If larger than the new word then not amb. cmamb0: lhld cmsptr ;Get the pointer to what parsed. cmamb1: dcr c ;Decrement the count. jm rskp ;If we are done then it is ambiguous. xchg ;Exchange the pointers. mov b,m ;Get the next char of the keyword inx h xchg ;Exchange the pointers. mov a,m ;Get the next parsed char.  inx h cpi 'a' ;Is it less than a? jm cmamb2 ;If so don't capitalize it. cpi 'z'+1 ;Is it more than z? jp cmamb2 ;If so don't capitalize it. ani 137O cmamb2: cmp b ;Are they equal? rnz ;If not then its not ambiguous. jmp cmamb1 ;Check the next char. ; ; cmofil - parse output filespec ; cmifil - parse input filespec ; here from: comnd cmofil: mvi a,0 ;Don't allow wildcards. ; jmp cmifil ;For now, the same as CMIFI. cmifil: sta cmfwld ;Set wildcard flag xchg ;Get the fcb address. shld cmfcb ;Save it. mvi e,0 ;Initialize char count. mvi m,0 ;Set the drive to default to current. inx h shld cmfcb2 xra a ;Initialize counter. cmifi0: mvi m,' ' ;Blank the FCB. inx h inr a cpi 0CH ;Twelve? jm cmifi0 cmifi1: call cmgtch ;Get another char. ora a ;Is it an action character? jp cmifi2 ani 7FH ;Turn off the action bit. cpi '?' ;A question mark? jnz cmif12 lxi h,cmaflg ;Blank the action flag. mvi m,0 lhld cmcptr ;Increment the buffer pointer. inx h ;(Gets decremented in 'cmgtch') shld cmcptr lhld cmdptr ;[jd] this is actually what is decremented inx h ;[jd] shld cmdptr ;[jd] jmp cmifi8 ;Treat like any other character. cmif12: cpi esc ;An escape? jnz cmif13 ;Try to recognize file-spec a'la TOPS-20 xra a sta cmaflg ;Turn off the action flag. lhld cmcptr ;Move the pointer to before the escape. dcx h shld cmcptr shld cmdptr lxi h,cmccnt ;Get the char count. dcr m ;Decrement it by one. mov a,e ;Save character count up to now. sta temp1 cpi 9 ;Past '.'? jm cmfrec ;No. dcr a ;Yes, don't count point. cmfrec: lhld cmfcb2 ;Fill the rest with CP/M wildcards. cmfrc1: cpi 11 ;Done? jp cmfrc2 ;Yes. mvi m,'?' inx h inr a jmp cmfrc1 cmfrc2: mvi c,sfirst ;Find first matching file? lhld cmfcb xchg call bdos cpi 0FFH jz cmfrc9 ;No, lose. lxi h,fcbblk ;Copy first file spec. call fspcop lxi h,fcbblk+10H ;Get another copy (in case not ambiguous). call fspcop mvi c,snext ;More matching specs? lhld cmfcb xchg call bdos cpi 0FFH jz cmfrc3 ;Only one. lxi h,fcbblk+10H ;Copy second file spec. call fspcop cmfrc3: lxi d,fcbblk ;Start comparing file names. lxi h,fcbblk+10H lda temp1 ;Bypass characters typed. cpi 9 ;Past '.'? jm cmfrc4 ;No. dcr a ;Yes, don't count point. cmfrc4: mvi c,0 cmfrl1: cmp c ;Bypassed? jz cmfrl2 ;Yes. inx d inx h inr c jmp cmfrl1 ;Repeat. cmfrl2: mov a,c ;Get file name characters processed. cpi 11 ;All done? jz cmfrc5 ;Yes. cpi 8 ;End of file name? jnz cmfrl3 ;No. lda temp1 ;Exactly at point? cpi 9 jz cmfrl3 ;Yes, don't output a second point. mvi a,'.' ;Output separator. call cmfput cmfrl3: ldax d ;Get a character from first file spec. inx d mov b,m ;Get from second file spec. inx h cmp b ;Compare. jnz cmfrc5 ;Ambiguous. inr c ;Same, count. cpi ' ' ;Blank? jz cmfrl2 ;Yes, don't output. call cmfput ;Put character into buffer. jmp cmfrl2 ;Repeat. cmfrc5: mov a,c ;Get count of characters processed. sta temp1 ;Save it. mvi a,'$' ;Get terminator. call cmfput ;Put it into buffer. lhld cmdptr ;Output recognized characters. xchg mvi c,prstr call bdos lhld cmcptr ;Remove terminator from buffer. dcx h shld cmcptr lxi h,cmccnt dcr m lda temp1 ;Characters processed. cpi 11 ;Complete file name. jz repars ;Yes, don't beep. cmfrc9: mvi c,conout mvi e,bell call bdos ;Ring the bell. jmp repars ; ; Continue file spec parsing. cmif13: mov a,e ;It must be a terminator. ora a ;Test the length of the file name. jz cmifi9 ;If zero complain. cpi 0DH jp cmifi9 ;If too long complain. jmp rskp ;Otherwise we have succeeded. cmifi2: cpi '.' jnz cmifi3 inr e mov a,e cpi 1H ;Any chars yet? jz cmifi9 ;No, give error. cpi 0AH ;Tenth char? jp cmifi9 ;Past it, give an error. mvi c,9H mvi b,0 lhld cmfcb dad b ;Point to file type field. shld cmfcb2 mvi e,9H ;Say we've gotten nine. jmp cmifi1 ;Get the next char. cmifi3: cpi ':' jnz cmifi4 inr e mov a,e cpi 2H ;Is it in the right place for a drive? jnz cmifi9 ;If not, complain. lhld cmfcb2 dcx h ;Point to previous character. mov a,m ;Get the drive name. sui '@' ;Get the drive number. shld cmfcb2 ;Save pointer to beginning of name field. dcx h ;Point to drive number. mov m,a ;Put it in the fcb. mvi e,0 ;Start character count over. jmp cmifi1 cmifi4: cpi '*' jnz cmifi7 lda cmfwld ;Wildcards allowed? cpi 0 jz cmif11 ;No,complain mov a,e cpi 8H ;Is this in the name or type field? jz cmifi9 ;If its where the dot should be give up. jp cmifi5 ;Type. mvi b,8H ;Eight chars. jmp cmifi6 cmifi5: mvi b,0CH ;Three chars. cmifi6: lhld cmfcb2 ;Get a pointer into the FCB. mvi a,'?' mov m,a ;Put a question mark in. inx h shld cmfcb2 inr e mov a,e cmp b jm cmifi6 ;Go fill in another. jmp cmifi1 ;Get the next char. cmifi7: cpi '0' jm cmifi9 cpi 'z'+1 jp cmifi9 cpi 'A' ;Don't capitalize non-alphabetics. jm cmifi8 ani 137O ;Capitalize. cmifi8: lhld cmfcb2 ;Get the pointer into the FCB. mov m,a ;Put the char there. inx h shld cmfcb2 inr e jmp cmifi1 cmifi9: lda cmstat cpi cmifin ;"silent"? jz r ;Yes,let him go w/o check lxi d,cmer02 cmif10: mvi c,prstr call bdos ret cmif11: lxi d,cmer03 ;Complain about wildcards. jmp cmif10 ; ; copy filename from buffer ; called with HL = destination, A = position (0-3) in buffer ; called by: cmifil fspcop: push psw ;Save A. lxi d,buff ;Get the right offset in the buffer. rlc rlc rlc rlc rlc add e inr a ;Bypass drive spec. mov e,a mvi b,11 ;Copy file name. fspcp1: ldax d inx d mov m,a inx h dcr b jnz fspcp1 pop psw ;Restore A. ret ; append character in A to command buffer ; called by: cmifil cmfput: push h ;Save H. lhld cmcptr ;Get buffer pointer. mov m,a ;Store in buffer. inx h shld cmcptr lxi h,cmccnt ;Count it. inr m pop h ;Restore H. ret ; ; Read characters from the command buffer. ; called by: cmtext, cmcfrm, cmkeyw, cmifil cmgtch: push h push b cmgtc1: lda cmaflg ora a ;Is it set. cz cminbf ;If the action char flag is not set get more. lhld cmdptr ;Get a pointer into the buffer. mov a,m ;Get the next char. inx h shld cmdptr cpi ' ' ;Is it a space? jz cmgtc2 cpi tab ;Or a tab? jnz cmgtc3 cmgtc2: lda cmsflg ;Get the space flag. ora a ;Was the last char a space? jnz cmgtc1 ;Yes, get another char. mvi a,0FFH ;Set the space flag. sta cmsflg mvi a,' ' pop b pop h jmp cmgtc5 cmgtc3: push psw xra a sta cmsflg ;Zero the space flag. pop psw pop b pop h cpi esc jz cmgtc5 cpi '?' ;Is the user curious? jz cmgtc4 cpi cr jz cmgtc4 cpi lf jz cmgtc4 cpi ff rnz ;Not an action char, just return. cmgtc4: push h lhld cmdptr dcx h shld cmdptr pop h cmgtc5: ori 80H ;Make the char negative to indicate it is ret ;a terminator. ; ; Read characters from console into command buffer, processing ; editing characters (^H, ^M, ^J, ^L, ^U, ^X, ?, del). ; called by: comnd, cmgtch cminbf: push psw push d push h lda cmaflg ;Is the action char flag set? ora a jnz cminb9 ;If so get no more chars. cminb1: lxi h,cmccnt ;Increment the char count. inr m mvi c,conin ;Get a char. call bdos lhld cmcptr ;Get the pointer into the buffer. mov m,a ;Put it in the buffer. inx h shld cmcptr cpi 25O ;Is it a ^U? jz cmnb12 ;Yes. cpi 30O ;Is it a ^X? jnz cminb2 cmnb12: call clrlin ;Clear the line. call prprmp ;Print the prompt [Toad Hall] lxi h,cmdbuf shld cmcptr ;Reset the point to the start. lxi h,cmccnt ;Zero the count. mvi m,0 jmp repars ;Go start over. cminb2: cpi 10O ;Backspace? jz cminb3 cpi del ;or Delete? jnz cminb4 call delchr ;Print the delete string. cminb3: lda cmccnt ;Decrement the char count by two. dcr a dcr a ora a ;Have we gone too far? jp cmnb32 ;If not proceed. mvi c,conout ;Ring the bell. mvi e,bell call bdos jmp cmnb12 ;Go reprint prompt and reparse. cmnb32: sta cmccnt ;Save the new char count. call clrspc ;Erase the character. lhld cmcptr ;Get the pointer into the buffer. dcx h ;Back up in the buffer. dcx h shld cmcptr jmp repars ;Go reparse everything. cminb4: cpi '?' ;Is it a question mark. jz cminb6 cpi esc ;Is it an escape? jz cminb6 cpi cr ;Is it a carriage return? jz cminb5 cpi lf ;Is it a line feed? jz cminb5 cpi ff ;Is it a formfeed? jnz cminb1 ;no - just store it and get another character. call clrtop cminb5: lda cmccnt ;Have we parsed any chars yet? cpi 1 jz prserr ;If not, just start over. cminb6: mvi a,0FFH ;Set the action flag. sta cmaflg jmp cminb9 cminb9: pop h pop d pop psw ret ; ;Little utility to print the prompt. (We do a LOT of these.) [Toad Hall] ;Enters with nothing. ;Destroys HL (and I suppose B and DE and A). prprmp: lhld cmprmp ;Get the prompt. xchg call prtstr ret IF lasm LINK CP4UTL ENDIF ;lasm [Toad Hall]  dreol ; Receive EOL char. squote: db dsquot ; Send quote char. rquote: db drquot ; Receive quote char. chktyp: db dschkt ; Checksum type desired tacflg: db tac AND 0FFH ; TACtrap status (zero = off, nonzero = on; ; when non-zero, is current TAC intercept character) tacchr: db tacval ; Desired TAC intercept character (even when off) ; space used by directory command; here because space calculation is ; (operating) system-dependent bmax: ds 2 ; highest block number on drive bmask: ds 1 ; (records/block)-1 bshiftf: ds 1 ; number of shifts to multiply by rec/block nnams: ds 1 ; counter for filenames per line lnksiz equ $-lnkflg ; length of linkage section, for consistency check. IF lasm ; If we're assembling with LASM, LINK CP4SYS ; get the next section. ENDIF;lasm ; CP4CPM.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This file duplicates the CP/M DIR and ERA functions so we don't have ; to exit. ; ; revision history: ; edit 3: July 8, 1984 (CJC) ; Merge modifications from Toad Hall: support LASM (linked by CP4TT, ; links to CP4WLD), use prcrlf where appropriate. ; ; edit 2: June 5, 1984 (CJC) ; documentation and formatting; delete unused code (dir13); add module ; version string. ; ; edit 1: May, 1984 (CJC) ; extracted from CPMBASE.M80 version 3.9; modifications are described in ; the accompanying .UPD file. ; cpmver: db 'CP4CPM.ASM (3) 8-Jul-84$' ; name, edit number, date npl EQU 04H ;Number of names per line for dir command. ; This is the DIR command. Display the name and size of all files ; matching the filespec. ; here from: kermit ; ; Note: This is abstracted from Keith Peterson's DIRF.ASM ; directory print function. Thanks again Keith. ; ; dir: lxi d,fcb ;Where to put the data, if any. mvi a,cmifin call comnd ;Parse a full or piece of file-spec jmp dir2 ;Didn't get a FULL file-spec jmp dir4 ;lets do it ; ; ;Make FCB all '?' to match any file dir2: lda fcb cpi ' ' ;CMIFIN leaves that as ' ' jnz dir2a ;he typed at least x: xra a sta fcb ;default drive dir2a: lxi h,fcb+1 mvi b,11 ;FN+FT count. dir3: mvi m,'?' ;Store '?'s in FCB. inx h dcr b jnz dir3 ;Print signon message and drive name dir4: lda fcb ora a ;if not zero, get default jnz dir4a lda curdsk ;get default dir4a: adi 'A'-1 ;Asciize it sta dnam14 ;Save it in message. call prcrlf lxi d,inms14 ;Point to message call prtstr ; ;Initialize number of names per line counter mvi a,npl ;Nr. names per line. sta nnams ;Init counter. ; call dir26 ;Get disk parameters dir5: call mfname ;get some names jnc dir6 ;got one jmp dir17 ;got none - do summary dir6: ;Check for console break mvi c,consta ;Ck status of kbd. call bdos ora a ;Any key pressed? jz dir6a ;nope, keep going mvi c,conin call bdos ;gobble key jmp dir17 ;and print summary only ;Print an entry dir6a: lxi h,fcb+1 ;point to Filename mvi b,8 ;File name length. call dir11 ;Type filename. mvi a,'.' ;Period after FN. call dir10 mvi b,3 ;Get the filetype. call dir11 call dir25 ;print size lxi h,nnams ;Point to names counter. dcr m ;One less on this line. push psw cnz dir7 ;No cr-lf needed, do fence. pop psw cz dir12 ;Cr-lf needed. jmp dir5 ;Print space, fence character, then space dir7: call dir9 mvi a,':' ;Fence character. call dir10 jmp dir9 ; dir8 - Print two spaces ; dir9 - Print one space ; dir10 - Type char in A register dir8: call dir9 dir9: mvi a,' ' dir10: push b push d push h mov e,a ;Char to E for CP/M. mvi c,conout ;Write char to console function. call bdos pop h pop d pop b ret ;Type (B) characters from memory (HL) dir11: mov a,m ani 7FH ;Remove CP/M 2.x attributes. call dir10 inx h dcr b jnz dir11 ret ;CR-LF routine. HL=NNAMS upon entry dir12: push b push d push h call prcrlf ;Print CR/LF [Toad Hall] pop h ;(did use call to dir10, but slooow) pop d pop b mvi m,npl ;Number of names per line. ret ;Exit - All done, return via jmp (as for all main commands) dir16: call prcrlf lda curdsk dcr a ;relative to 0 mov e,a mvi c,logdsk call bdos ;back to "logged in" disk jmp kermit ;...and return to kermit. ; ;Determines free space remaining ; dir17: xra a sta mfflg1 ;clean up MFNAME sta mfflg2 lda fcb ; get drive number from FCB ora a jz dir18 ; default? dcr a ; no, make requested drive current drive. mov e,a mvi c,logdsk call bdos dir18: call sysspc ; get space available for current drive push h lxi d,inms15 ;"Drive " call prtstr lda fcb ;If no drive, get ora a ;logged in drive jnz dir24 mvi c,rddrv call bdos inr a dir24: adi 'A'-1 sta inms16 lxi d,inms16 ;"x has " call prtstr pop h ;Get number of bytes available call nout lxi d,inms17 ;"K bytes free" call prtstr jmp dir16 ;all done ;Compute the size of the file dir25: mvi c,cflsz ;get file-size lxi d,fcb call bdos lda fcbrno ;shift least sign. part lxi b,0 ;init bc mov l,a ani 7 jz dir250 ;even K lxi b,1 ;save for later dir250: push b ;save 0 or 1 to add to size mvi b,3 ;shift 3 bits dir25a: xra a ;clear sign lda fcbrno+1 ;get most sig byte rar ;shift right sta fcbrno+1 ;put back lda fcbrno ;get least sig part rar sta fcbrno dcr b ;loop 3 times jnz dir25a mov l,a ;size in HL lda fcbrno+1 mov h,a pop b ;get 0 or 1 dad b ;round up to KB used lda bmask ;get (sectors/block)-1 rrc rrc ;get (K/block)-1 rrc ani 1FH mov c,a dad b ;add (K/block)-1 to size to round up cma ;make a mask ana l ;truncate after rounding up mov l,a push h lxi b,-10 ;subtract 10 dad b jc dir25d ;>= 10 call dir8 ; print a leading space jmp dir25e dir25d: pop h ;get size again push h lxi b,-100 ;subtract 100 dad b jc dir25e ;>= 100 call dir9 ; print another leading space dir25e: call dir9 ;a space pop h ;get size back call nout ;..go print it mvi a,'k' ;..and follow with K size call dir10 ret dir26: mvi c,gtdpar ;current DISK PARAMETER BLOCK call bdos inx h inx h mov a,m ;Get Block Shift Factor sta bshiftf inx h ;Bump to Block Mask mov a,m ;get it sta bmask inx h inx h mov e,m ;Get Max Block number inx h mov d,m xchg shld bmax ;Put it away ret ; ; ERA command - erase a CP/M file ; here from: kermit era: mvi a,cmifi ;Parse a file-spec lxi d,fcb ;into FCB call comnd jmp kermit ;bad parse lxi d,fcb mvi c,sfirst ;check if valid call bdos inr a ;0 if FILE not found jnz era1 ;found at least one lxi d,erms15 ;"unable to find file" call prtstr jmp kermit era1: lxi d,fcb mvi c,delf call bdos lxi d,inms18 ;" File(s) erased" call prtstr jmp kermit IF lasm LINK CP4WLD ENDIF;lasm [Toad Hall]  because space calculation is ; (operating) system-dependent bmax: ds 2 ; highest block number on drive bmask: ds 1 ; (records/block)-1 bshiftf: ds 1 ; number of shifts to multiply by rec/block nnams: ds 1 ; counter for filenames per line lnksiz equ $-lnkflg ; length of linkage section, for consistency check. IF lasm ; If we're assembling with LASM, LINK CP4SYS ; get the next section. ENDIF;lasm ; CP4KER.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This is the header for the system-independent portion of KERMIT, which ; consists of the following files (in this order): ; CP4KER.ASM - this file ; CP4DEF.ASM - definitions for both KERMIT and KERSYS ; CP4MIT.ASM - initialization, main loop, miscellaneous commands ; (BYE, EXIT, LOG, SET, SHOW, and STATUS) ; CP4PKT.ASM - the KERMIT protocol handler (SEND, RECEIVE, LOGOUT, ; and FINISH commands) ; CP4TT.ASM - the transparent commands (TRANSMIT, CONNECT) ; CP4CPM.ASM - CP/M commands (DIR, ERA) ; CP4WLD.ASM - the wildcard handler ; CP4CMD.ASM - the command parser ; CP4UTL.ASM - utility routines and data ; ; When building the system-independent part with M80 or MAC80, CP4KER ; INCLUDEs the other files; when building with LASM, each file LINKs to ; the next file. ; ; For now, the system-dependent routines are all in CP4SYS.ASM, with ; the actual configuration defined in CP4TYP.ASM. ; ; revision history (latest first): ; edit 1: July 27, 1984 (CJC) ; Created to allow assembly of Kermit by LASM as well as MAC80 and M80. ; ; Version 4.02 of Kermit consists of the following edit levels: ; cp4ker.asm edit 1 ; cp4def.asm edit 2 ; cp4pkt.asm edit 3 ; cp4tt.asm edit 3 ; cp4cpm.asm edit 3 ; cp4wld.asm edit 3 ; cp4cmd.asm edit 3 ; cp4utl.asm edit 2 ; cp4lnk.asm edit 3 (cp4lnk.asm is not assembled with cp4ker, but it ; defines the linkage area expected by cp4ker, and so must ; match the description in cp4utl.asm. ; ; Version 4.02 of Kermit has been tested with the following edit levels of ; the system-dependent files: ; cp4typ.asm edit 3 ; cp4sys.asm edit 3 ; FALSE equ 0 TRUE equ NOT FALSE cp4ker equ TRUE ; building system-independent part ; ; Assembler type. Define the appropriate one TRUE, the rest FALSE. (We can't ; use ASM, because it cannot handle multiple input files) mac80 EQU FALSE ; For assembly via MAC80 cross-assembler. m80 EQU FALSE ; For assembly via Microsoft's M80. lasm EQU TRUE ; For assembly via LASM, a public-domain ; assembler. ; ; Get the other modules... IF lasm ; If we're linking, go on to the next file. LINK CP4DEF ENDIF;lasm ; If we're still here, we must be using M80 or MAC80. M80 doesn't ; like ENDs inside conditionals, but the END statement has to be ; in CP4UTL for LASM (otherwise, we'd need a file containing just an ; END statement). So, we leave off the IF m80 OR mac80 conditional ; that ought to be around these INCLUDEs. No problem until the next ; incompatible assembler comes along... INCLUDE CP4DEF.ASM ; definitions INCLUDE CP4MIT.ASM ; initialization, main loop, some commands INCLUDE CP4PKT.ASM ; KERMIT protocol handler INCLUDE CP4TT.ASM ; transparent communication handler INCLUDE CP4CPM.ASM ; CP/M command support (DIR, ERA) INCLUDE CP4WLD.ASM ; wildcard handler INCLUDE CP4CMD.ASM ; command parser INCLUDE CP4UTL.ASM ; Various utilities and data, and END [ToadHall] END ; MAC80 ignores END's in included files...  because space calculation is ; (operating) system-dependent bmax: ds 2 ; highest block number on drive bmask: ds 1 ; (records/block)-1 bshiftf: ds 1 ; number of shifts to multiply by rec/block nnams: ds 1 ; counter for filenames per line lnksiz equ $-lnkflg ; length of linkage section, for consistency check. IF lasm ; If we're assembling with LASM, LINK CP4SYS ; get the next section. ENDIF;lasm ; CP4MIT.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This file contains the system-independent initialization, the main ; loop, and the commands that don't have any place better to go ; (BYE, EXIT, HELP, LOG, SET, SHOW, and STATUS). ; ; revision history: ; edit 4: August 3, 1984 (CJC) ; Remove "mover" from entry section, as it now lives in CP4SYS. ; ; edit 3: July 27, 1984 (CJC) ; Merge LASM support from Toad Hall: most of CP4MIT is now in CP4UTL. ; When assembling with LASM, CP4MIT is linked by CP4DEF; it links to ; CP4PKT. Add SET TACTRAP command. Separate out display routines so ; we can eventually do "SHOW ". Save both bytes of baud ; rate in speed, and check both bytes when displaying baud rate. Move ; header info to CP4KER.ASM. Add onoff and chkkey routines to simplify ; SET command (Toad Hall) ; ; edit 2: June 8, 1984 ; formatting and documentation; delete unreferenced variables and some ; unnecessary labels; move setpar here from cp4pkt; add module version ; string; make this version 4.01. ; ; edit 1: May, 1984 ; extracted from CPMBASE.M80 version 3.9; modifications are described ; in the accompanying .UPD file. ; ASEG ORG 100H jmp start ; Bypass entry section ; ; Entry section for system-independent part. This contains ; jumps to routines needed by the system support module. ; entries: jmp kermit ; reentry address jmp nout ; output HL in decimal entsiz equ $-entries ; length of entry section ; ; End of entry section. As a consistency check, the expected ; length of this section is stored by the system-dependent ; module in the linkage section at the end of Kermit, and ; tested at initialization. kerver: db 'CP4MIT.ASM (4) 3-Aug-84$' ; name, edit number, date ; ; ; Initialization ; start: lxi h,0 ; Clear out hl pair dad sp ; and fetch the system stack pointer shld oldsp ; and save for later restoral lxi sp,stack ; move in our own stack. lxi d,version ; print Kermit version call prtstr ; before we do too much mvi c,rddrv ;Get our logged in drive call BDOS inr a ;relative 1 sta CURDSK ;and save it for later ; ; Make sure the overlay is in place... ; lhld lnkflg mov a,h ora l ; if lnkflg is still zero, jz start1 ; the configuration overlay is missing. lxi d,-lnksiz ; if it's not equal to lnksiz, dad d ; we've probably got the wrong mov a,h ; version of the configuration overlay. ora l jnz start2 lhld lnkent ; make sure the overlay knows how long lxi d,-entsiz ; our entry section is, so they don't miss. dad d mov a,h ora l jnz start2 ; might be ok. call sysinit ; do system-dependent initialization lxi d,inms26 ; offer some advice on getting help call prtstr jmp kermit ; Start main loop. start1: lxi d,erms20 ; "Kermit has not been configured" call prtstr ; print error message jmp exit2 ; and exit. start2: lxi d,erms21 ; "Consistency check on configuration failed" call prtstr ; print error message jmp exit2 ; and exit. ; ;This is the main KERMIT loop. It prompts for and gets the users commands. kermit: lxi sp,stack ; get new stack pointer, old one might be bad. call selcon ; make sure console is selected. xra a sta mfflg1 ;reset MFNAME sta mfflg2 ;ditto lda curdsk ; update the prompt adi 'A'-1 sta kerm1 lxi d,kerm call prompt ;Prompt the user. lxi d,comtab lxi h,tophlp call keycmd lxi h,kermtb ;Get the address of the jump table. mov c,a mvi b,0 dad b pchl kermtb: jmp telnet jmp exit jmp help jmp log jmp read jmp send jmp setcom ;Set is an assembler keyword jmp show jmp status jmp finish jmp logout jmp bye jmp dir ;do directory jmp era ;do "ERA"se file jmp xmit ; here from: log, setcom, read, cfmcmd kermt3: lxi d,ermes3 ;"Not confirmed" call prtstr jmp kermit ;Do it again. ; ; This is the BYE command. It tells the remote KERSRV to logout, ; then exits. bye: call cfmcmd call logo ;Tell the main frame to logout. jmp kermit ;If it fails, don't exit. call sysbye ; success. do system-dependent cleanup jmp exit1 ;Exit Kermit. ; This is the EXIT command. It leaves KERMIT and returns to CP/M. ; alternate entries: exit1, from BYE command; ; exit2, from initialization (if it fails) exit: call cfmcmd ; confirm... exit1: call sysexit ; do system-dependent termination exit2: lhld oldsp ;Get back the system stack sphl ;and restore it. ret ;Then return to system. ; This is the HELP command. It gives a list of the commands. help: call cfmcmd lxi d,tophlp ;The address of the help message. call prtstr jmp kermit ; ; This is the LOG command. It logs a session to a file. log: mvi a,cmofi ;Parse an input file spec. lxi d,fcb call comnd jmp kermt3 call cfmcmd lxi h,logflg mvi m,0FFH ;Set the log flag. lxi h,buff shld bufpnt mvi c,delf ;Delete the file if it exists. lxi d,fcb call bdos xra a sta fcb+0CH ;Zero the extent. sta fcb+0EH ;Must be zero for MAKEF or OPENF. sta fcb+20H ;Zero the current record. mvi c,makef ;Now create it. lxi d,fcb call bdos cpi 0FFH ;Is the disk full? jnz kermit ; lxi d,erms17 ;If so tell the user call prtstr jmp kermit ; ; This is the SET command. setcom: lxi d,settab ;Parse a keyword from the set table. lxi h,sethlp call keycmd lxi h,setjtb ;Get the address of the jump table. mov c,a mvi b,0 dad b pchl setjtb: jmp escape ;00H SET ESC jmp ibmset ;03H SET IBM jmp locall ;06H SET LOCAL jmp kermt3 ;09H SET RECEIVE (not currently used) jmp setsnd ;0CH SET SEND (not currently used) jmp filwar ;0FH SET WARNING jmp setcpm ;12H SET FILE-MODE jmp parset ;15H SET PARITY jmp blkset ;18H SET BLOCK-CHECK-TYPE jmp vt52em ;1BH SET VT52 jmp prtset ;1EH SET PORT (system-dependent) jmp baud ;21H SET BAUD (system-dependent) jmp setdisk ;24H SET DEFAULT-DISK jmp setprn ;27H SET PRINTER jmp settim ;[jd] 2AH SET TIMER jmp setdbg ;2DH SET DEBUG jmp settac ;30H SET TACTRAP [Toad Hall] ; ;SET BLOCK-CHECK-TYPE command. blkset: lxi d,blktab ;Get the address of the block-check table lxi h,blkhlp ;And the address of the help text call chkkey ;Go check input (val returns in A). sta chktyp ;Save desired checksum type jmp kermit ;Go get another command ;SET DEFAULT DISK command setdisk:lxi d,fcb mvi a,cmifin ;get "file-spec" silently call comnd jmp setdi1 setdi1: lda fcb ora a ;Was a drive specified? (if zero, no) jnz setdi2 ;he typed a drive-spec lda curdsk ;he didn't - give him default setdi2: sta curdsk mvi c,inbdos ;reset disks call bdos lda curdsk dcr a ;LOGDSK is relative 0 mov e,a mvi c,logdsk call bdos ;and "LOG" it jmp kermit ;all done ; ;SET SEND command. (not supported yet) setsnd: lxi d,stsntb ;Parse a keyword from the set send table. lxi h,stshlp call keycmd lxi h,stsjtb ;Get the address of the jump table. mov c,a mvi b,0 dad b pchl ; dispatch table for SET SEND subcommands stsjtb: jmp stpdch jmp stpad ; SET SEND PADDING command. does nothing. stpad: call cfmcmd jmp kermit ; SET SEND PAD-CHAR command. does nothing. stpdch: call cfmcmd jmp kermit ; ; This is the SET ESCAPE character subcommand. escape: call cfmcmd lxi d,escmes ;Get the address of the escape message. call prtstr mvi c,conin ;Get the char. call bdos sta escchr ;Store the new escape character. jmp kermit ; This is the SET LOCAL-ECHO subcommand. locall: call onoff ;Get on/off setting [Toad Hall] sta ecoflg ;Store local echo flag.  jmp kermit ; This is the SET PRINTER ON/OFF subcommand setprn: call onoff ;Get on/off setting [Toad Hall] sta prnflg ;Store printer flag jmp kermit ; This is the SET DEBUG ON/OFF subcommand setdbg: call onoff ;Get on/off setting [Toad Hall] sta dbgflg ;Store debug flag jmp kermit ;[jd] this is the SET TIMER subcommand settim: call onoff ;Get on/off setting [Toad Hall] sta timflg ;Store timer flag value jmp kermit ;This is the SET FILE-WARNING subcommand filwar: call onoff ;Get on/off setting [Toad Hall] sta flwflg ;Store file-warning flag. jmp kermit ; This is the SET IBM command. ibmset: call onoff ;Get on/off setting [Toad Hall] sta ibmflg ;Store IBM flag. ora a ;Is it turned on? jz ibmst1 ;If not, set parity to the default. mvi a,ibmpar ;Get the IBM parity. mvi b,1 ;Set local echo on. jmp ibmst2 ibmst1: mvi a,defpar mvi b,0 ;Set local echo off. ibmst2: sta parity ;Save them. mov a,b sta ecoflg sta timflg ;[jd] timer is same as local echo jmp kermit ; ; SET FILE-MODE command. setcpm: lxi d,typtab lxi h,typhlp call chkkey ;Get and confirm keyword, or die trying sta cpmflg ;Set the CPM flag. jmp kermit ; This is the SET PARITY subcommand. parset: lxi d,partab lxi h,parhlp call chkkey ;Get and confirm keyword, or die trying sta parity ;Set the parity flag. jmp kermit ; This is the SET TACTRAP subcommand. ; options are ON, OFF, or CHARACTER. (for CHARACTER, we request the ; new TAC Intercept character, and turn the TACtrap on) settac: lxi d,tactab lxi h,tachlp call chkkey ;Get and confirm keyword ora a ;Was it "OFF" (zero)? jz settc2 ;If so, go disable TACtrap. cpi 1 ;Was it "ON"? jz settc1 ;If so, go enable TACtrap. lxi d,tacmes ;"CHARACTER". request new TAC Intercept char. call prtstr mvi c,conin ;Get the char. call bdos sta tacchr ;Store the new TAC Intercept character. settc1: lda tacchr ;Copy tacchr to tacflg to enable TACtrap. settc2: sta tacflg ;Enable/disable TACtrap jmp kermit ; This is the SET VT52-EMULATION subcommand. vt52em: lda vtflg ;get the flag value cpi 0ffH ;0ffH means not allowed - jz notimp ; say it's not implemented. call onoff ;Get keyword (ON or OFF) sta vtflg ;Set the VT52 emulation flag. jmp kermit ; ; Note: For the SET BAUD and SET PORT commands, which might not be ; supported for the current system, the command tables are stored in ; the overlay. We locate them through pointers in the linkage area: ; spdtab for SET BAUD, prttab for SET PORT. The contents of spdtab ; (or prttab) is the address of the beginning of the table (the table ; does NOT begin at spdtab). If the address is zero, the command is ; not supported. If the table address is nonzero, then there is a ; corresponding help message pointed to by (NOT starting at) spdhlp ; or prthlp. ; This is the SET BAUD command baud: lhld spdtab ; get pointer to speed table mov a,h ora l ; test for NULL (zero) jz notimp ; if so, say it's not implemented xchg ; move speed table address to DE lhld spdhlp ; get pointer to speed help text call keycmd push d ; save selected speed call cfmcmd ; confirm... pop h ; restore speed to HL shld speed ; save all 16 bits of speed value xchg ; move speed to DE call sysspd ; do system-dependent speed setting. jmp kermit ; return to command level ; This is the SET PORT command prtset: lhld prttab ; get pointer to port table mov a,h ora l ; test for NULL jz notimp ; not supported if pointer was null. xchg ; move port table address to DE lhld prthlp ; get pointer to port help text call keycmd push d ; save selected port entry call cfmcmd ; confirm... pop h ; restore table address to HL call sysprt ; go do port stuff jmp kermit ; ; Subroutines for SET subcommands ; onoff - accept "ON" or "OFF" keyword. ; returns: ; success: value in A (non-zero = ON) ; error: no return to caller. print error message and return to ; main loop. onoff: lxi d,ontab lxi h,onhlp ;Fall through to check input. [Toad Hall] ; chkkey - parse and confirm keyword. ; called with: ; DE/ address of keyword table ; HL/ address of help text ; returns: ; success: low byte of keyword value (from table) in A. ; error: no return to caller. print error message and return to ; main loop. (Since the main loop reloads the stack pointer, ; we don't have to attempt to clean up the stack here) chkkey: call keycmd ; Parse a keyword (might not return) sta temp1 ; Save the parsed value call cfmcmd ; Request confirmation (might not return) lda temp1 ; Get saved value ret ; Return ; ; This is the SHOW command. show: call cfmcmd ;* Reconcile this and status. call stat01 ;For now just cop out. jmp kermit ; This is the STATUS command. status: call cfmcmd call stat01 jmp kermit ; processor for SHOW, STATUS and S commands ; called by: show, status, intchr stat01: lda fileio ;Are we in transmit? ora a jz sta01b ;No lxi d,xmtst ;Yes,say so call prtstr sta01b: call staeco ; Tell about local echo flag lda vtflg ; Get the VT52 emulation flag cpi 0ffH ; Supported for this terminal? cnz stavt ; If so, tell whether it's on or off. call stafil ; Tell about file type call staibm ; Tell about IBM flag call stawrn ; Tell about file-warning flag call stalpt ; Tell about printer copy flag call stapar ; Tell about parity lhld spdtab ; Got a speed table? (is pointer nonzero?) mov a,h ora l cnz staspd ; If so, tell what speed we're running. call stabcc ; Tell current block check type call staesc ; Tell current escape character call statim ; Tell about timer flag call statac ; Tell about TAC flag/intercept character. ret ; Show the value of the LOCAL-ECHO flag (On or Off). staeco: lxi d,locst ;Get the address of the local echo string. call prtstr lda ecoflg ;Get the local echo flag. jmp staton ;Say ON or OFF, and return ; Show the value of the VT52-EMULATION flag (On, Off, or Not Supported). stavt: lxi d,vtemst ; Get the address of the VT52 emulation string. call prtstr lda vtflg ; Get the VT52 emulation flag. cpi 0ffH ; Is it supported? jnz staton ; If so, say ON or OFF, and return jmp notimp ; Not supported. print appropriate message. ; Show the value of the FILE-MODE flag (ASCII, Binary, or Default). stafil: lxi d,cpmst ; Get the address of the file mode message. call prtstr lda cpmflg ; Get the file mode flag. lxi d,defstr ; Assume Default (0). ora a ; Is it? jz prtstr ; If so, say so, and return. lxi d,ascstr ; Not default, assume ASCII cpi 1 ; Is it ASCII? jz prtstr ; Say ASCII, and return lxi d,binstr ; Not default or ASCII, must be binary jmp prtstr ; Print type, and return. ; Show the value of the IBM-MODE flag (On or Off). staibm: lxi d,ibmst ;IBM string. call prtstr lda ibmflg ; Get IBM flag. jmp staton ; Print its value and return ; Show the value of the FILE-WARNING flag (On or Off). stawrn: lxi d,filst ; File warning string. call prtstr lda flwflg ; File warning flag. jmp staton ; Say ON or OFF ; Show the value of the PRINTER flag (On or Off). stalpt: lxi d,prst ;Printer copy string call prtstr lda prnflg ;Printer ON/OFF flag jmp staton ; Say ON or OFF ; Show the value of the PARITY flag (Odd, Even, Mark, Space, or None). stapar: lxi d,parst ;Parity string. call prtstr lda parity ;Get the parity setting. lxi d,pnonst ;Assume parity is NONE cpi parnon ;Were we right? jz prtstr ;Yep, go say None, and return lxi d,pmrkst ;Get ready to say Mark cpi parmrk ;Is it mark? jz prtstr ;Yep, go say Mark, and return lxi d,pspcst ;Get ready to say Space cpi parspc ;Is it space? jz prtstr ;Yep, go say Space, and return lxi d,poddst ;Get ready to say Odd cpi parodd ;Is it odd? jz prtstr ;Yep, go say Odd, and return lxi d,pevnst ;Must be Even. jmp prtstr ;Say Even, and return. ; Show the current line speed (if known). staspd: lxi d,spdst call prtstr lda speed ;Get current speed. lxi h,spdust ;Assume undefined. cpi 0FFH ;Is it? jz stat73 ;Yes. lhld spdtab ;Start scanning keyword table. mov d,m ; get count of entries inx h ; advance over it. stat70: mov b,m ;Get string length. inr b ;Account for $. inx h shld temp1 ;Save string pointer. stat71: inx h ;Loop over string. dcr b jnz stat71 mov c,m ;Get speed value cmp c ;Match? jz stat72 ;Yes. inx h ;Bump to next keyword. inx h dcr d ; decrement entry count jnz stat70 ; if more left, check them. lxi h,spdust ; can't find it. say it's undefined. jmp stat73 ; print the message. stat72: lhld temp1 ;Restore saved string pointer. stat73: xchg ;Set into DE for display. jmp prtstr ; print it, and return. ; Show the current BLOCK-CHECK-TYPE (1-, 2-, or 3-character). stabcc: lxi d,bckst ;Get the string call prtstr ;Print "Block check type: " lda chktyp ;Get the type (character 1, 2, or 3) mov e,a ;Put into E mvi c,conout ;Want to print it call BDOS ;Do so lxi d,bckst1 ;Get rest of text ("-character") jmp prtstr ;Print it and return ; Print the current escape character staesc: lxi d,escst ;Escape string. call prtstr call escpr ;Print the escape char. jmp prcrlf ;Print CR/LF and return [Toad Hall] ; Show the value of the TIMER flag statim: lxi d,timmsg ;[jd] call prtstr ;[jd] lda timflg jmp staton ;Tell whether it's on or off. ; Show TACTrap status (On or Off, and intercept character) statac: lxi d,tacst ;"Current TACTrap status/char: " call prtstr lxi d,offstr ;Assume set off lda tacflg ;Get the TACTrap char/flag ora a ;Is it off? jz prtstr ;Yep, go print OFF... mvi c,conout ;Display... mov e,a ;...the current intercept char call bdos jmp prcrlf ; Display current state of a boolean flag. ; called with A/ value (zero = Off, non-zero = On) staton: lxi d,onstr ; Assume it's on. ora a ; Is it on? jnz prtstr ; If so, say so, then return. lxi d,offstr ; No, say off. jmp prtstr ; Print the string, then return. ; Print "(not implemented)". ; here from vt52em, baud, prtset, stavt notimp: lxi d,inms12 ; Say it's not implemented. call prtstr jmp kermit ; Return to main loop. IF lasm ; If using LASM, chain to the next file. LINK CP4PKT ENDIF;lasm lities and data, and END [ToadHall] END ; MAC80 ignores END's in included files...  because space calculation is ; (operating) system-dependent bmax: ds 2 ; highest block number on drive bmask: ds 1 ; (records/block)-1 bshiftf: ds 1 ; number of shifts to multiply by rec/block nnams: ds 1 ; counter for filenames per line lnksiz equ $-lnkflg ; length of linkage section, for consistency check. IF lasm ; If we're assembling with LASM, LINK CP4SYS ; get the next section. ENDIF;lasm ; CP4PKT.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This file contains the (system-independent) routines that implement ; the KERMIT protocol, and the commands that use them: ; RECEIVE, SEND, FINISH, and LOGOUT. ; ; revision history: ; edit 3: July 27, 1984 ; add link directive for LASM. CP4PKT is linked by CP4MIT, and links ; to CP4TT. Add Toad Hall TACtrap to permit operations through a TAC. ; ; edit 2: June 8, 1984 ; formatting and documentation; remove some unused labels; move setpar ; to cp4mit.m80; add module version string; make all arithmetic on ; 'pktnum' modulo 64; apply defaults correctly for missing parameters ; in send-init packet (and corresponding ack). ; ; edit 1: May, 1984 ; extracted from CPMBASE.M80 version 3.9; modifications are described ; in the accompanying .UPD file. ; pktver: db 'CP4PKT.ASM (3) 27-Jul-84$' ; name, edit number, date ; RECEIVE command ; here from: kermit read: lxi d,data ;Where to put the text (if any.) mvi a,cmtxt call comnd ;Get either some text or a confirm. jmp kermt3 ; Didn't get anything. ora a ;Get any chars? jz read1 ;Nope, just a regular send. sta argblk+1 ;Store the number of chars. xchg ;Get pointer into HL. mvi m,'$' ;Put in a dollar sign for printing. call init ;Clear the line and initialize the buffers. call scrfln ;Position cursor lxi d,data ;Print the file name call prtstr mvi a,'1' ;Start with single character checksum sta curchk ;Save the type xra a ;Start a packet zero. sta argblk mvi a,'R' ;Receive init packet. call spack ;Send the packet. jmp kermt3 ; Die! jmp read12 read1: call init ;Clear the line and initialize the buffers. read12: xra a sta czseen ;Clear the ^X/^Z flag initially. lxi h,0 shld numpkt ;Set the number of packets to zero. shld numrtr ;Set the number of retries to zero. sta pktnum ;Set the packet number to zero. sta numtry ;Set the number of tries to zero. call scrnrt ;Position cursor lxi h,0 call nout ;Write the number of retries. mvi a,'R' sta state ;Set the state to receive initiate. ;... ; ;RECEIVE state table switcher. read2: call scrnp ;Position cursor lhld numpkt call nout ;Write the current packet number. lda state ;Get the state. cpi 'D' ;Are we in the DATA receive state? jnz read3 call rdata jmp read2 read3: cpi 'F' ;Are we in the FILE receive state? jnz read4 call rfile ;Call receive file. jmp read2 read4: cpi 'R' ;Are we in the Receive-Initiate state? jnz read5 call rinit lda state ;[jd] get new state cpi 'F' ;[jd] went into receive state? jnz read2 ;[jd] no lxi d,inms24 ;[jd] yes, get receiving... message call finmes ;[jd] go print it jmp read2 read5: cpi 'C' ;Are we in the Receive-Complete state? jnz read6 lxi d,infms3 ;Put in "Complete" message. lda czseen ;Or was it interrupted? ora a ; . . . jz read5a ;No. xra a ;Yes, clear flag. sta czseen ; ... lxi d,inms13 ;Issue "interrupted" message. read5a: call finmes ;Print completion message in right place. jmp kermit read6: cpi 'A' ;Are we in the Receive-"Abort" state? jnz read7 read7: lxi d,infms4 ;Anything else is equivalent to "abort". call finmes jmp kermit ; ; Receive routines ; Receive init ; called by: read rinit: lda numtry ;Get the number of tries. cpi imxtry ;Have we reached the maximum number of tries? jm rinit2 lxi d,ermes4 call error3 ;Move cursor and print an error message. jmp abort ;Change the state to abort. rinit2: inr a ;Increment it. sta numtry ;Save the updated number of tries. mvi a,'1' ;Reset block check type to single character sta curchk ;Store as current type for initialization call rpack ;Get a packet. jmp nak ; Trashed packet: nak, retry. cpi 'S' ;Is it a send initiate packet? jnz rinit3 ;If not see if its an error. lda numtry ;Get the number of tries. sta oldtry ;Save it. xra a sta numtry ;Reset the number of tries. lda argblk ;Returned packet number. (Synchronize them.) call countp lda argblk+1 ;Get the number of arguments received. lxi h,data ;Get a pointer to the data. call spar ;Get the data into the proper variables. lxi h,data ;Get a pointer to our data block. call rpar ;Set up the receive parameters. sta argblk+1 ;Store the returned number of arguments. mvi a,'Y' ;Acknowledge packet. call spack ;Send the packet. jmp abort ; Failed, abort. lda inichk ;Now switch to agreed upon check-type sta curchk ;For all future packets mvi a,'F' ;Set the state to file send. sta state ret rinit3: cpi 'E' ;Is it an error packet. jnz nak0 ;If not NAK whatever it is. call error jmp abort ; ; Receive file ; called by: read rfile: lda numtry ;Get the number of tries. cpi maxtry ;Have we reached the maximum number of tries? jm rfile1 lxi d,ermes5 call error3 ;Move cursor and print an error message. jmp abort ;Change the state to abort. rfile1: inr a ;Increment it. sta numtry ;Save the updated number of tries. call rpack ;Get a packet. jmp nak ; Trashed packet: nak, retry. cpi 'S' ;Is it a send initiate packet? jnz rfile2 ; No, try next type. lda oldtry ;Get the number of tries. cpi imxtry ;Have we reached the maximum number of tries? jm rfil12 ;If not proceed. lxi d,ermes4 call error3 ;Move cursor and print an error message. jmp abort ;Change the state to abort. rfil12: inr a ;Increment it. sta oldtry ;Save the updated number of tries. lda pktnum ;Get the present packet number. dcr a ;Decrement ani 3FH ; modulo 64 mov b,a lda argblk ;Get the packet's number cmp b ;Is the packet's number one less than now? jnz nak0 ;No, NAK and try again. call updrtr ;Update the retry count. xra a sta numtry ;Reset the number of tries. lxi h,data ;Get a pointer to our data block. call rpar ;Set up the parameter information. sta argblk+1 ;Save the number of arguments. mvi a,'Y' ;Acknowledge packet. call spack ;Send the packet. jmp abort ; Failed, abort. ret rfile2: cpi 'Z' ;Is it an EOF packet? jnz rfile3 ; No, try next type. lda oldtry ;Get the number of tries. cpi maxtry ;Have we reached the maximum number of tries? jm rfil21 ;If not proceed. lxi d,ermes6 call error3 ;Move cursor and print an error message. jmp abort ;Change the state to abort. rfil21: call tryagn ret rfile3: cpi 'F' ;Start of file? jnz rfile4 call compp jnz nak0 ;No, NAK it and try again. call countp call gofil ;Get a file to write to, and init output buffer. jmp abort lda numtry ;Get the number of tries. sta oldtry ;Save it. call ackp mvi a,'D' ;Set the state to data receive. sta state lda czseen ;Check if we punted a file cpi 'Z' ;and didn't want any more rz ;If that was the request, keep telling other end xra a ;Otherwise, clear flag (^X is only for one file) sta czseen ;And store the flag back ret rfile4: cpi 'B' ;End of transmission. jnz rfile5 call compp jnz nak0 ;No, NAK it and try again. xra a ;No data. (Packet number already in argblk). sta argblk+1 mvi a,'Y' ;Acknowledge packet. call spack ;Send the packet. jmp abort mvi a,'C' ;Set the state to complete. sta state ret rfile5: cpi 'E' ;Is it an error packet. jnz abort call error jmp abort ; ; Receive data ; called by: read rdata: lda numtry ;Get the number of tries. cpi maxtry ;Have we reached the maximum number of tries? jm rdata1 lxi d,erms10 call error3 ;Display error message. jmp abort ;Change the state to abort. rdata1: inr a ;Increment it. sta numtry ;Save the updated number of tries. call rpack ;Get a packet. jmp nak ; Trashed packet: nak, retry. cpi 'D' ;Is it a data packet? jnz rdata2 ; No, try next type. call compp jz rdat14 lda oldtry ;Get the number of tries. cpi maxtry ;Have we reached the maximum number of tries? jm rdat12 ;If not proceed. lxi d,erms10 call error3 ;Display err msg. jmp abort ;Change the state to abort. rdat12: call tryagn ret rdat14: call countp lda numtry ;Get the number of tries. sta oldtry ;Save it. lda argblk+1 ;Get the length of the data. call ptchr jmp abort ; Unable to write out chars;abort. xra a sta numtry ;Reset the number of tries. sta argblk+1 ;No data. (Packet number still in argblk.) mov c,a ;Assume no data lda czseen ;Check if control-X typed ora a ; . . . jz rdat15 ;Zero if not typed mov c,a ;Get the type of character typed mvi a,1 ;One data character sta argblk+1 ;Save the count mov a,c ;Get the possible data character sta data ;Store in data area rdat15: mvi a,'Y' ;Acknowledge packet. call spack ;Send the packet. jmp abort ret rdata2: cpi 'F' ;Start of file? jnz rdata3 ; No, try next type. lda oldtry ;Get the number of tries. cpi maxtry ;Have we reached the maximum number of tries? jm rdat21 ;If not proceed. lxi d,ermes5 call error3 ;Display err msg. jmp abort ;Change the state to abort. rdat21: call tryagn ret rdata3: cpi 'Z' ;Is it a EOF packet? jnz rdata4 ;Try and see if its an error. call compp jnz nak0 ;No, NAK it and try again. call countp lda argblk+1 ;Get the data length cpi 1 ;Have one item? jnz rdat33 ;If not, ignore data lda data ;Yes, get the character cpi 'D' ;Is it a 'D' for discard? jz rdat36 ;If so, punt file rdat33: lhld bufpnt ;Get the dma pointer. lda chrcnt ;Get the number of chars left in the DMA. rdat34: dcr a ;Lower the count. ora a jm rdat35 ;If full then stop. mvi m,'Z'-100O ;Put in a ^Z for EOF. inx h ;Point to the next space. jmp rdat34 rdat35: call outbuf ;Output the last buffer. jmp abort ; Give up if the disk is full. mvi c,closf ;Close up the file. lxi d,fcb call bdos xra a ;Since we kept the file, sta czseen ;don't say it was discarded. rdat36: lda numtry ;Get the number of tries. sta oldtry ;Save it. call ackp mvi a,'F' sta state ret rdata4: cpi 'E' ;Is it an error packet. jnz abort call error jmp abort ; ; SEND command ; here from: kermit send: mvi a,cmifi ;Parse an input file spec. lxi d,fcb ;Give the address for the FCB. call comnd jmp kermit ; Give up on bad parse. call cfmcmd call mfname ;handle (multi) files jnc send14 ;got a valid file-name lxi d,erms15 call error3 ;Display error msg. jmp kermit send14: call init ;Clear the line and initialize the buffers. xra a sta pktnum ;Set the packet number to zero. sta numtry ;Set the number of tries to zero. sta wrn8 ;[jd] we haven't sent the 8-bit-lost warning lxi h,0 shld numpkt ;Set the number of packets to zero. shld numrtr ;Set the number of retries to zero. call scrnrt ;Position cursor lxi h,0 call nout ;Write the number of retries. mvi a,'1' ;Reset to use single character checksum sta curchk ;For startup mvi a,'S' sta state ;Set the state to receive initiate. ;... ; ;SEND state table switcher send2: call scrnp ;Position cursor lhld numpkt call nout ;Write the packet number. lda state ;Get the state. cpi 'D' ;Are we in the data send state? jnz send3 call sdata jmp send2 send3: cpi 'F' ;Are we in the file send state? jnz send4 call sfile ;Call send file. jmp send2 send4: cpi 'Z' ;Are we in the EOF state? jnz send5 call seof jmp send2 send5: cpi 'S' ;Are we in the send initiate state? jnz send6 call sinit lda state ;[jd] get state back cpi 'F' ;[jd] into file send state yet? jnz send2 ;[jd] no lxi d,inms23 ;[jd] yes, print sending... call finmes ;[jd] jmp send2 send6: cpi 'B' ;Are we in the eot state? jnz send7 call seot jmp send2 send7: cpi 'C' ;Are we in the send complete state? jnz send8 ;No... lxi d,infms3 ;Yes, write "Complete" message. lda czseen ;Or was it interrupted? ora a ; . . . jz send7a ;No. lxi d,inms13 ;Yes, then say "Interrupted" instead. send7a: call finmes jmp kermit send8: cpi 'A' ;Are we in the send "abort" state? jnz send9 lxi d,infms4 ;Print message. call finmes jmp kermit send9: lxi d,infms4 ;Anything else is equivalent to "abort". call finmes jmp kermit ; ; Send routines ; Send initiate ; called by: send sinit: lda numtry ;Get the number of tries. cpi imxtry ;Have we reached the maximum number of tries? jm sinit2 lxi d,erms14 call error3 ;Display ermsg jmp abort ;Change the state to abort. sinit2: inr a ;Increment it. sta numtry ;Save the updated number of tries. mvi a,'1' ;Reset to use single character checksum sta curchk ;For startup lda chktyp ;Get our desired block check type sta inichk ;Store so we tell other end lxi h,data ;Get a pointer to our data block. call rpar ;Set up the parameter information. sta argblk+1 ;Save the number of arguments. lda numpkt ;Get the packet number. sta argblk mvi a,'S' ;Send initiate packet. call spack ;Send the packet. jmp abort ; Failed, abort. call rpack ;Get a packet. jmp r ; Trashed packet don't change state, retry. cpi 'Y' ;ACK? jnz sinit3 ;If not try next. call compp rnz ;If not try again. call countp lda argblk+1 ;Get the number of pieces of data. lxi h,data ;Pointer to the data. call spar ;Read in the data. lda numtry ;Get the number of tries. sta oldtry ;Save it. xra a sta numtry ;Reset the number of tries. lda inichk ;Get the agreed upon block check type sta curchk ;Store as type to use for packets now mvi a,'F' ;Set the state to file send. sta state call getfil ;Open the file. ret ; assume success; mfname thinks the file exists. sinit3: cpi 'N' ;NAK? jnz sinit4 ;If not see if its an error. call updrtr ;Update the number of retries. lda pktnum ;Get the present packet number. inr a ;Increment ani 3FH ; modulo 64 mov b,a lda argblk ;Get the packet's number. cmp b ;Is the packet's number one more than now? rnz ;If not assume its for this packet, go again. xra a sta numtry ;Reset number of tries. mvi a,'F' ;Set the state to file send. sta state ret sinit4: cpi 'E' ;Is it an error packet. jnz abort call error jmp abort ; ; Send file header ; called by: send sfile: lda numtry ;Get the number of tries. cpi maxtry ;Have we reached the maximum number of tries? jm sfile1 lxi d,erms14 call error3 jmp abort ;Change the state to abort. sfile1: inr a ;Increment it. sta numtry ;Save the updated number of tries. xra a ;Clear A sta czseen ;No control-Z or X seen lxi h,data ;Get a pointer to our data block. shld datptr ;Save it. lxi h,fcb+1 ;Pointer to the file name in the FCB. shld fcbptr ;Save position in FCB. mvi b,0 ;No chars yet. mvi c,0 sfil11: mov a,b cpi 8H ;Is this the ninth char? jnz sfil12 ;If not proceed. mvi a,'.' ;Get a dot. lhld datptr mov m,a ;Put the char in the data packet. inx h shld datptr ;Save position in data packet. inr c sfil12: inr b ;Increment the count. mov a,b cpi 0CH ;Twelve? jp sfil13 lhld fcbptr mov a,m ani 7fH ;Turn off CP/M 2 or 3's high bits. inx h shld fcbptr ;Save position in FCB. cpi '!' ;Is it a good character? jm sfil11 ;If not get the next. lhld datptr mov m,a ;Put the char in the data packet. inx h shld datptr ;Save position in data packet. inr c jmp sfil11 ;Get another. sfil13: mov a,c ;Number of char in file name. sta argblk+1 lhld datptr mvi a,'$' mov m,a ;Put in a dollar sign for printing. call scrfln ;Position cursor lxi d,data ;Print the file name call prtstr lda pktnum ;Get the packet number. sta argblk mvi a,'F' ;File header packet. call spack ;Send the packet. jmp abort ; Failed, abort. call rpack ;Get a packet. jmp r ; Trashed packet don't change state, retry. cpi 'Y' ;ACK? jnz sfile2 ;If not try next. call compp rnz ;If not hold out for the right one. sfil14: call countp lda numtry ;Get the number of tries. sta oldtry ;Save it. xra a sta numtry ;Reset the number of tries. call gtchr ;Fill the first data packet jmp sfil16 ;Error go see if its EOF. ; ;Got the chars, proceed. sta size ;Save the size of the data gotten. mvi a,'D' ;Set the state to data send. sta state ret sfil16: cpi 0FFH ;Is it EOF? jnz abort ;If not give up. mvi a,'Z' ;Set the state to EOF. sta state ret sfile2: cpi 'N' ;NAK? jnz sfile3 ;Try if error packet. call updrtr ;Update the number of retries. lda pktnum ;Get the present packet number. inr a ;Increment ani 3FH ; modulo 64 mov b,a lda argblk ;Get the packet's number. cmp b ;Is the packet's number one more than now? rnz ;If not go try again. jmp sfil14 ;Just as good as a ACK;go to the ACK code. sfile3: cpi 'E' ;Is it an error packet. jnz abort call error jmp abort ; ; Send data ; called by: send sdata: lda numtry ;Get the number of tries. cpi maxtry ;Have we reached the maximum number of tries? jm sdata1 lxi d,erms14 call error3 jmp abort ;Change the state to abort. sdata1: inr a ;Increment it. sta numtry ;Save the updated number of tries. lxi h, data ;Get a pointer to our data block. shld datptr ;Save it. lxi h,filbuf ;Pointer to chars to be sent. shld cbfptr ;Save position in char buffer. mvi b,1 ;First char. sdat11: lhld cbfptr mov a,m inx h shld cbfptr ;Save position in char buffer. mov c,a ;[jd] preserve character temporarily lda quot8 ;[jd] doing eighth-bit quoting? ora a ;[jd] mov a,c ;[jd] restore char jnz sdat4 ;[jd] using eighth-bit quoting, no warning lda parity ;[jd] get parity cpi parnon ;[jd] none? mov a,c ;[jd] restore character jz sdat4 ;[jd] no parity, leave char alone lda wrn8 ;[jd] look at warning flag ora a ;[jd] have we already given the warning? jnz sdat5 ;[jd] yes, skip this mov a,c ;[jd] restore character... ani 80h ;[jd] examine parity jz sdat5 ;[jd] no parity, no warning. call parwrn ;[jd] ...print warning - parity lost mvi a,0ffh ;[jd] remember that we sent the message sta wrn8 ;[jd] sdat5: mov a,c ;[jd] restore character again ani 7fh ;[jd] strip parity so not checksummed sdat4: lhld datptr mov m,a ;Put the char in the data packet. inx h shld datptr ;Save position in data packet. inr b ;Increment the count. lda size ;Get the number of chars in char buffer. cmp b ;Have we transfered that many? jp sdat11 ;If not get another. lda size ;Number of char in char buffer. sta argblk+1 lda pktnum ;Get the packet number. sta argblk mvi a,'D' ;Data packet. call spack ;Send the packet. jmp abort ; Failed, abort. call rpack ;Get a packet. jmp r ; Trashed packet don't change state, retry. cpi 'Y' ;ACK? jnz sdata2 ;If not try next. call compp rnz ;If not hold out for the right one. lda argblk ;Get the packet number back call countp lda numtry ;Get the number of tries. sta oldtry ;Save it. xra a sta numtry ;Reset the number of tries. lda argblk+1 ;Get the data length cpi 1 ;Check if only 1 character? jnz sdat15 ;If not, just continue lda data ;Got one character, get it from data cpi 'Z' ;Want to abort entire stream? jnz sdat14 ;If not, check for just this file sta czseen ;Yes, remember it sdat14: cpi 'X' ;Desire abort of current file? jnz sdat15 ;If not, just continue sta czseen ;Yes, remember that sdat15: lda czseen ;Also get control-Z flag ora a ;Check if either given jz sdat12 ;If neither given, continue mvi a,'Z' ;Change state to EOF sta state ; . . . ret ;And return sdat12: call gtchr jmp sdat13 ;Error go see if its EOF. sta size ;Save the size of the data gotten. ret sdat13: cpi 0FFH ;Is it EOF? jnz abort ;If not give up. mvi a,'Z' ;Set the state to EOF. sta state ret sdata2: cpi 'N' ;NAK? jnz sdata3 ;See if is an error packet. call updrtr ;Update the number of retries. lda pktnum ;Get the present packet number. inr a ;Increment ani 3FH ; modulo 64 mov b,a lda argblk ;Get the packet's number. cmp b ;Is the packet's number one more than now? rnz ;If not go try again. jmp sdat12 ;Just as good as a ACK;go to the ACK code. sdata3: cpi 'E' ;Is it an error packet. jnz abort call error jmp abort ; ; Send EOF ; called by: send seof: lda numtry ;Get the number of tries. cpi maxtry ;Have we reached the maximum number of tries? jm seof1 lxi d,erms14 call error3 jmp abort ;Change the state to abort. seof1: inr a ;Increment it. sta numtry ;Save the updated number of tries. lda pktnum ;Get the packet number. sta argblk xra a sta argblk+1 ;No data. lda czseen ;Check if C-Z or C-X typed ora a ; . . . jz seof14 ;If not aborted, just keep going mvi a,'D' ;Tell other end to discard packet sta data ;Store in data portion mvi a,1 ;One character sta argblk+1 ;Store the length seof14: mvi a,'Z' ;EOF packet. call spack ;Send the packet. jmp abort ; Failed, abort. call rpack ;Get a packet. jmp r ; Trashed packet don't change state, retry. cpi 'Y' ;ACK? jnz seof2 ;If not try next. call compp rnz ;If not hold out for the right one. seof12: call countp lda numtry ;Get the number of tries. sta oldtry ;Save it. xra a sta numtry ;Reset the number of tries. mvi c,closf ;Close the file. lxi d,fcb call bdos ;* Check if successful lda czseen ;Desire abort of entire stream? cpi 'Z' ;Desire abort of entire stream? jz seof13 ;If so, just give up now call mfname ;Get the next file. jc seof13 ; No more. call getfil ;and open it (assume success) xra a ;Clear A sta czseen ;Since we have not aborted this file mvi a,'F' ;Set the state to file send. sta state ret seof13: mvi a,'B' ;Set the state to EOT. sta state ret seof2: cpi 'N' ;NAK? jnz seof3 ;Try and see if its an error packet. call updrtr ;Update the number of retries. lda pktnum ;Get the present packet number. inr a ;Increment ani 3FH ; modulo 64 mov b,a lda argblk ;Get the packet's number. cmp b ;Is the packet's number one more than now? rnz ;If not go try again. jmp seof12 ;Just as good as a ACK;go to the ACK code. seof3: cpi 'E' ;Is it an error packet. jnz abort call error jmp abort ; ; Send EOT ; called by: send seot: lda numtry ;Get the number of tries. cpi maxtry ;Have we reached the maximum number of tries? jm seot1 lxi d,erms14 call error3 jmp abort ;Change the state to abort. seot1: inr a ;Increment it. sta numtry ;Save the updated number of tries. lda pktnum ;Get the packet number. sta argblk xra a sta argblk+1 ;No data. mvi a,'B' ;EOF packet. call spack ;Send the packet. jmp abort ; Failed, abort. call rpack ;Get a packet. jmp r ; Trashed packet don't change state, retry. cpi 'Y' ;ACK? jnz seot2 ;If not try next. call compp rnz ;If not hold out for the right one. seot12: call countp lda numtry ;Get the number of tries. sta oldtry ;Save it. xra a sta numtry ;Reset the number of tries. mvi a,'C' ;Set the state to file send. sta state ret seot2: cpi 'N' ;NAK? jnz seot3 ;Is it error. call updrtr ;Update the number of retries. lda pktnum ;Get the present packet number. inr a ;Increment ani 3FH ; modulo 64 mov b,a lda argblk ;Get the packet's number. cmp b ;Is the packet's number one more than now? rnz ;If not go try again. jmp seot12 ;Just as good as a ACK;go to the ACK code. seot3: cpi 'E' ;Is it an error packet. jnz abort call error jmp abort ; ; This routine sets up the data for init packet (either the ; Send_init or ACK packet). ; called by: rinit, rfile, sinit rpar: lda rpsiz ;Get the receive packet size. adi ' ' ;Add a space to make it printable. mov m,a ;Put it in the packet. inx h ;Point to the next char. lda rtime ;Get the receive packet time out. adi ' ' ;Add a space. mov m,a ;Put it in the packet. inx h lda rpad ;Get the number of padding chars. adi ' ' mov m,a inx h lda rpadch ;Get the padding char. adi 100O ;Uncontrol it. ani 7FH mov m,a inx h lda reol ;Get the EOL char. adi ' ' mov m,a inx h lda rquote ;Get the quote char. mov m,a inx h mvi m,'Y' ;[jd] we know how to do 8-bit quoting lda parity ;[jd] cpi parnon ;[jd] parity none? jz rpar1 ;[jd] yes, keep going lda qbchr ;[jd] no, better request 8-bit quoting mov m,a rpar1: inx h ;Advance to next lda chktyp ;Get desired block check type mov m,a ;Store it inx h ;Advance pointer mvi a,08H ;Six pieces of data. ret ; ; This routine reads in all the send_init packet information. ; called by: rinit, sinit spar: sta temp4 ;Save the number of arguments. ; Initialize some variables to their required default values, so we use ; the right values even if the remote Kermit doesn't send the full packet: ; ; we don't do anything with timeout values yet. ; ; no default pad count/pad character? mvi a,cr ; EOL character = carriage-return sta seol mvi a,'#' ; quote character = '#' sta squote mvi a,'&' ; eighth-bit quote character = '&' sta qbchr mvi a,'1' ; block-check = 1-character-checksum sta inichk ; mov a,m ;Get the max packet size. sbi ' ' ;Subtract a space. sta spsiz ;Save it. lda temp4 cpi 3 ;Fewer than three pieces? rm ;If so we are done. inx h inx h ;Increment past the time out info. mov a,m ;Get the number of padding chars. sbi ' ' sta spad lda temp4 cpi 4 ;Fewer than four pieces? rm ;If so we are done. inx h mov a,m ;Get the padding char. adi 100O ;Re-controlify it. ani 7FH sta spadch lda temp4 cpi 5 ;Fewer than five pieces? rm ;If so we are done. inx h mov a,m ;Get the EOL char. sbi ' ' sta seol lda temp4 cpi 6 ;Fewer than six pieces? rm ;If so we are done. inx h mov a,m ;Get the quote char. sta squote lda temp4 ;Get the amount of data supplied cpi 7 ;Have an 8-bit quote? rm ;If not there, all done inx h ;Yes, get the character mvi a,0 ;[jd] sta quot8 ;[jd] assume not quoting mov a,m ;Get the supplied character cpi 'N' ;[jd] No? jz spar1 ;[jd] then don't try to do it cpi ' ' ;[jd] maybe they don't know about it... jz spar1 ;[jd] then don't try to do it. cpi 'Y' ;[jd] Yes? jnz spar2 ;[jd] if not 'Y', assume it's a quote char. lda parity ;[jd] using parity? cpi parnon ;[jd] no, don't need quoting... jz spar1 ;[jd] mvi a,0ffh ;[jd] else turn on... sta quot8 ;[jd] ...quote flag jmp spar1 spar2: sta qbchr ;[jd] use their quote char (should validate) mvi a,0ffh sta quot8 ;[jd] turn quote flag and fall thru... spar1: lda temp4 ;Determine if block check type given cpi 8 ;Is the field there? rm ;If not, all done inx h ;Point to the character mov a,m ;Get the value mov b,a ;Copy value lda chktyp ;Get our type cmp b ;Is it our desired type? rnz ; If not, use default (1-character-checksum) sta inichk ; Match, store as type to use after init ret ; and return ; ; Copy characters from packet to disk ; called by: rdata ptchr: sta temp1 ;Save the size. lxi h,data ;Beginning of received packet data. shld outpnt ;Remember where we are. lda rquote mov b,a ;Keep the quote char in b. mvi c,0 ;[jd] assume no 8-bit quote char lda quot8 ;[jd] doing 8-bit quoting? ora a jz ptchr1 ;[jd] no, keep going lda qbchr ;[jd] else get 8-bit quote char mov c,a ;[jd] keep this in c ptchr1: lxi h,temp1 dcr m ;Decrement # of chars in packet. jm rskp ;Return successfully if done. lxi h,chrcnt ;Number of chars remaining in dma. dcr m ;Decrement. jp ptchr2 ;Continue if space left. call outbuf ;Output it if full. jmp r ; Error return if disk is full. ptchr2: lhld outpnt ;Get position in output buffer. mov a,m ;Grab a char. inx h shld outpnt ;and bump pointer. mvi e,0 ;[jd] assume nothing to OR in. cmp c ;[jd] is it the binary quote char? jnz ptch2a ;[jd] no, keep going mvi e,80h ;[jd] include parity bit lda temp1 dcr a sta temp1 ;[jd] decrement character count mov a,m ;[jd] get next character inx h shld outpnt ptch2a: cmp b ;Is it the quote char? jnz ptchr3 ;[jd] changed to ptchr3 so includes parity mov a,m ;Get the quoted character inx h shld outpnt ;and bump pointer. lxi h,temp1 dcr m ;Decrement # of chars in packet. mov d,a ;Save the char. ani 80H ;Turn off all but the parity bit. ora e ;[jd] let parity come from either (???) mov e,a ;Save the parity bit. mov a,d ;Get the char. ani 7FH ;Turn off the parity bit. cmp b ;Is it the quote char? jz ptchr3 ;If so just go write it out. cmp c ;[jd] maybe it's the 8-bit prefix character? jz ptchr3 ;[jd] then don't controllify. mov a,d ;Get the char. adi 40H ;Make the character a control char again. ani 7FH ;Modulo 128. ptchr3: ora e ;Or in the parity bit. lhld bufpnt ;Destination buffer. mov m,a ;Store it. inx h shld bufpnt ;Update the pointer jmp ptchr1 ;and loop to next char. ; ; Fill a data packet from file ; called by: sfile, sdata gtchr: lda squote ;Get the quote char. mov c,a ;Keep quote char in c. lda curchk ;Get current block check type sui '1' ;Get the extra overhead mov b,a ;Get a copy lda spsiz ;Get the maximum packet size. sui 5 ;Subtract the overhead. sub b ;Determine max packet length sta temp1 ;This is the number of chars we are to get. lxi h,filbuf ;Where to put the data. shld cbfptr ;Remember where we are. mvi b,0 ;No chars. gtchr1: lda temp1 dcr a ;Decrement the number of chars left. jp gtchr2 ;Go on if there is more than one left. mov a,b ;Return the count in A. jmp rskp gtchr2: sta temp1 lda chrcnt ;Space left in the DMA. dcr a ;* Can improve order here. jm gtchr3 sta chrcnt jmp gtchr4 gtchr3: call inbuf ;Get another buffer full. jmp gtch30 ; If no more return what we got. jmp gtchr4 ;If we got some, proceed. gtch30: mov a,b ;Return the count in A. ora a ;Get any chars? jnz rskp ;If so return them. jmp gtceof ;If not, say we found the end of the file. gtchr4: lhld bufpnt ;Position in DMA. mov a,m ;Get a char from the file. inx h shld bufpnt mov d,a ;Save the char. ani 80H ;Turn off all but parity. mov e,a ;Save the parity bit. jz gtch4a ;[jd] no parity, skip this check... lda quot8 ;[jd] doing eighth-bit quoting? ora a jz gtch4a ;[jd] no, just proceed normally lda temp1 ;[jd] get space remaining cpi 2 ;[jd] 3 chrs left (one cnted already)? jm gtchr9 ;[jd] no, skip this dcr a ;[jd] decrement space remaining sta temp1 ;[jd] put back. lhld cbfptr ;[jd] Position in character buffer. lda qbchr ;[jd] get quote character mov m,a ;]jd] Put the quote char in the buffer. inx h ;[jd] increment destination buffer pointer shld cbfptr ;[jd] store the pointer back inr b ;[jd] Increment the char count. mvi e,0 ;[jd] no parity bit to OR in. ;[jd] fall thru... gtch4a: mov a,d ;Restore the char. ani 7FH ;Turn off the parity. mov d,a ;[jd] save here for later... cpi ' ' ;Compare to a space. jm gtchr5 ;If less then its a control char, handle it. cpi del ;Is the char a delete? jz gtchr5 ;Go quote it. lda quot8 ; Are we doing 8th-bit quoting? ora a jz gtch4c ; if not, skip this test and restore character. lda qbchr ; get 8th-bit quote character cmp d ; same as current character? jz gtch4b ; yes, have to quote it... gtch4c: mov a,d ; no. get character back again. cmp c ;Is it the quote char? jnz gtchr8 ;If not proceed. gtch4b: lxi h,temp1 ;[jd] point to char count dcr m ;[jd] decrement (know room for at least one) lhld cbfptr ;Position in character buffer. mov m,c ;Put the (quote) char in the buffer. inx h shld cbfptr inr b ;Increment the char count. mov a,d ;[jd] restore character again jmp gtchr8 gtchr5: ora e ;Turn on the parity bit. cpi ('Z'-100O) ;Is it a ^Z? jnz gtchr7 ;If not just proceed. lda cpmflg ;Was the file created by CPM... cpi 1 ;in ASCII-mode ? jz gtch52 ;Control-Z stops text cpi 2 ;in BINARY mode? jz gtchr6 ;Yes, pass the ^Z ;At this point file-mode is DEFAULT. ;If the rest of the record is filled with ^Zs, we're at EOF, otherwise ;its a regular character. lhld bufpnt ;since CHRCNT is ZERO at EOF-time lda chrcnt ;(set by INBUF5 B.G.E) mov d,a ;Get the number of chars left in the DMA. gtch51: dcr d mov a,d jp gtch53 ;Any chars left? gtch52: xra a ;If not, get a zero. sta chrcnt ;Say no more chars in buffer. mov a,b ;Return the count in A. jmp rskp ;Scan rest of buffer for non ^Z -- If we find a non ^Z, fall into gtchr6. ;If we get to the end of the buffer before finding a non ^Z, fall into gtch52. gtch53: mov a,m ;Get the next char. inx h ;Move the pointer. cpi ('Z'-100O) ;Is it a ^Z? jz gtch51 ;If so see if the rest are. gtchr6: mvi a,('Z'-100O) ;Restore the ^Z. gtchr7: sta temp2 ;Save the char. lxi h,temp1 ;Point to the char total remaining. dcr m ;Decrement it. lhld cbfptr ;Position in character buffer. mov m,c ;Put the quote in the buffer. inx h shld cbfptr inr b ;Increment the char count. lda temp2 ;Get the control char back. adi 40H ;Make the non-control. ani 7fH ;Modulo 200 octal. gtchr8: lhld cbfptr ;Position in character buffer. ora e ;Or in the parity bit. mov m,a ;Put the char in the buffer. inx h shld cbfptr inr b ;Increment the char count. jmp gtchr1 ;Go around again. gtchr9: ;[jd] not enough room left in buffer... lhld bufpnt dcx h shld bufpnt ;[jd] back up over last character lxi h,chrcnt ;[jd] point to character count inr m ;[jd] increment it mov a,b ;[jd] count of chars transferred jmp rskp ;[jd] return it gtceof: mvi a,0FFH ;Get a minus one. ret ; ; Get the file name (including host to micro translation) ; called by: rfile gofil: lxi h,data ;Get the address of the file name. shld datptr ;Store the address. lxi h,fcb+1 ;Address of the FCB. shld fcbptr ;Save it. xra a sta temp1 ;Initialize the char count. sta temp2 sta fcb ;Set the drive to default to current. mvi b,' ' gofil1: mov m,b ;Blank the FCB. inx h inr a cpi 0CH ;Twelve? jm gofil1 gofil2: lhld datptr ;Get the NAME field. mov a,m cpi 'a' ;Force upper case jm gofl2a ; ani 5FH ; gofl2a: inx h cpi '.' ;Seperator? jnz gofil3 shld datptr ;[jd] update ptr (moved from above) lxi h,fcb+9H shld fcbptr lda temp1 sta temp2 mvi a,9H sta temp1 jmp gofil6 gofil3: ora a ;Trailing null? jz gofil7 ;Then we're done. shld datptr ;[jd] no, can update ptr now. lhld fcbptr mov m,a inx h shld fcbptr  lda temp1 ;Get the char count. inr a sta temp1 cpi 8H ;Are we finished with this field? jm gofil2 gofil4: sta temp2 lhld datptr mov a,m inx h shld datptr ora a jz gofil7 cpi '.' ;Is this the terminator? jnz gofil4 ;Go until we find it. gofil6: lhld datptr ;Get the TYPE field. mov a,m cpi 'a' ;Force upper case jm gofl6a ; ani 5FH ; gofl6a: ora a ;Trailing null? jz gofil7 ;Then we're done. ;[jd] move above two lines so we don't increment pointer if char is null inx h shld datptr lhld fcbptr mov m,a inx h shld fcbptr lda temp1 ;Get the char count. inr a sta temp1 cpi 0CH ;Are we finished with this field? jm gofil6 gofil7: lhld datptr mvi m,'$' ;Put in a dollar sign for printing. call scrfln ;Position cursor lxi d,data ;Print the file name call prtstr lda flwflg ;Is file warning on? ora a jz gofil9 ;If not, just proceed. mvi c,openf ;See if the file exists. lxi d,fcb call bdos cpi 0FFH ;Does it exist? jz gofil9 ;If not create it. lxi d,infms5 call error3 lda temp2 ;Get the number of chars in the file name. ora a jnz gofil8 lda temp1 sta temp2 gofil8: mvi b,0 mov d,b ;Zero d for dad index into filename inr a ;Replace next character after filename cpi 9H ;Is the first field full? jnz gofl80 mvi b,0FFH ;Set a flag saying so. dcr a gofl80: mov e,a ;Keep current, replace index in d,e. gofl81: lxi h,fcb ;Get the FCB. dad d ;Add in the character number. mvi m,'&' ;Replace the char with an ampersand. push b push d lxi h,fcb ;Trim off any CP/M 2.2 attribute bits mvi c,1+8+3 ;so they do not affect the new file gofl82: mov a,m ; ani 7FH ; mov m,a ; inx h ; dcr c ; jnz gofl82 ; mvi c,openf ;See if the file exists. lxi d,fcb call bdos pop d pop b cpi 0FFH ;Does it exist? jz gofl89 ;If not create it. mov a,b ;Get the field-full flag. ora a ;Incr. or decr. ? jz gofl83 ;Jump if increment dcr e ;Decrement the number of chars. mov a,e ora a jz gofl88 ;If no more, die. jmp gofl81 gofl83: inr e ;Increment the number of chars. mov a,e cpi 9H ;Are we to the end? jm gofl81 ;If not try again. lda temp2 ;Get the original size. mov e,a mvi b,0FFH ;Set flag saying field-full, decrement jmp gofl81 gofl88: lxi d,erms16 ;Tell user that we can't rename it. call prtstr ret gofl89: mvi c,8 ;[jd] # of chars in name lxi d,fnbuf ;[jd] point to destination lxi h,fcb+1 ;[jd] source of name mvi b,0 ;[jd] first-time-thru flag gof89a: mov a,m ;[jd] get a char from the name inx h ;[jd] pass it cpi ' ' ;[jd] end of this part of name? jz gof89b ;[jd] yes, skip rest... stax d ;[jd] else drop char off inx d ;[jd] increment dest ptr dcr c ;[jd] decrement count jnz gof89a ;[jd] and continue if more to go gof89b: mov a,b ;[jd] ora a ;[jd] first time thru? jnz gof89c ;[jd] no, no period mvi a,'.' ;[jd] period between parts stax d ;[jd] inx d ;[jd] mvi b,0ffh ;[jd] not first time thru anymore mvi c,3 ;[jd] length of this part lxi h,fcb+9 ;[jd] start of extension jmp gof89a ;[jd] keep copying gof89c: mvi a,'$' stax d ;[jd] end the name string lxi d,fnbuf ;[jd] Print the file name call prtstr gofil9: mvi c,delf ;Delete the file if it exists. lxi d,fcb call bdos xra a sta fcb+0CH ;Zero the extent. sta fcb+0EH ;Must be zero for MAKEF or OPENF. sta fcb+20H ;Zero the current record. mvi a,bufsiz ;Say output buffer is empty sta chrcnt lxi h,buff ;Set pointer to start of output buffer shld bufpnt mvi c,makef ;Now create it. lxi d,fcb call bdos cpi 0FFH ;Is the disk full? jnz rskp lxi d,erms11 call error3 ret ; ; This is the FINISH command. It tells the remote KERSRV to exit. ; here from kermit finish: call cfmcmd xra a sta numtry ;Inititialize count. mvi a,'1' ;Reset block check type to single character sta curchk ; . . . finsh1: lda numtry ;How many times have we tried? cpi maxtry ;Too many times? jm finsh3 ;No, try it. finsh2: lxi d,erms18 ;Say we couldn't do it. call prtstr jmp kermit ;Go home. finsh3: inr a ;Increment the number of tries. sta numtry xra a sta argblk ;Make it packet number zero. mvi a,1 sta argblk+1 ;One piece of data. lxi h,data mvi m,'F' ;Finish running Kermit. mvi a,'G' ;Generic command packet. call spack jmp finsh2 ; Tell the user and die. call rpack ;Get an acknowledgement. jmp finsh1 ; Go try again. cpi 'Y' ;ACK? jz kermit ;Yes, we are done. cpi 'E' ;Is it an error packet? jnz finsh1 ;Try sending the packet again. call error1 ;Print the error message. jmp kermit ; ; This is the LOGOUT command. It tells the remote KERSRV to logout. ; here from: kermit logout: call cfmcmd call logo ;Send the logout packet. jmp kermit ;Go get another command jmp kermit ; whether we succeed or not. ; do logout processing. ; called by: bye, logout logo: xra a sta numtry ;Inititialize count. mvi a,'1' ;Reset block check type to single character sta curchk ; . . . logo1: lda numtry ;How many times have we tried? cpi maxtry ;Too many times? jm logo3 ;No, try it. logo2: lxi d,erms19 ;Say we couldn't do it. call prtstr ret ;Finished. logo3: inr a ;Increment the number of tries. sta numtry xra a sta argblk ;Make it packet number zero. mvi a,1 sta argblk+1 ;One piece of data. lxi h,data mvi m,'L' ;Logout the remote host. mvi a,'G' ;Generic command packet. call spack jmp logo2 ; Tell the user and die. call rpack ;Get an acknowledgement jmp logo1 ; Go try again. cpi 'Y' ;ACK? jz rskp ;Yes, we are done. cpi 'E' ;Is it an error packet? jnz logo1 ;Try sending the packet again. call error1 ;Print the error message. ret ;All done. ; ; Packet routines ; Send_Packet ; This routine assembles a packet from the arguments given and sends it ; to the host. ; ; Expects the following: ; A - Type of packet (D,Y,N,S,R,E,F,Z,T) ; ARGBLK - Packet sequence number ; ARGBLK+1 - Number of data characters ; Returns: nonskip if failure ; skip if success ; called by: read, rinit, rfile, rdata, sinit, sfile, sdata, seof, seot, ; finish, logout, nak, ackp spack: sta argblk+2 lxi h,packet ;Get address of the send packet. mvi a,soh ;Get the start of header char. mov m,a ;Put in the packet. inx h ;Point to next char. lda curchk ;Get current checksum type sui '1' ;Determine extra length of checksum mov b,a ;Copy length lda argblk+1 ;Get the number of data chars. adi ' '+3 ;Real packet character count made printable. add b ;Determine overall length mov m,a ;Put in the packet. inx h ;Point to next char. lxi b,0 ;Zero the checksum AC. mov c,a ;Start the checksum. lda argblk ;Get the packet number. adi ' ' ;Add a space so the number is printable. mov m,a ;Put in the packet. inx h ;Point to next char. add c mov c,a ;Add the packet number to the checksum. mvi a,0 ;Clear A (Cannot be XRA A, since we can't ; touch carry flag) adc b ;Get high order portion of checksum mov b,a ;Copy back to B lda argblk+2 ;Get the packet type. mov m,a ;Put in the packet. inx h ;Point to next char. add c mov c,a ;Add the packet number to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B spack2: lda argblk+1 ;Get the packet size. ora a ;Are there any chars of data? jz spack3 ; No, finish up. dcr a ;Decrement the char count. sta argblk+1 ;Put it back. mov a,m ;Get the next char. inx h ;Point to next char. add c mov c,a ;Add the packet number to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B jmp spack2 ;Go try again. spack3: lda curchk ;Get the current checksum type cpi '2' ;Two character? jz spack4 ;Yes, go handle it jnc spack5 ;No, go handle CRC if '3' mov a,c ;Get the character total. ani 0C0H ;Turn off all but the two high order bits.  ;Shift them into the low order position. rlc ;Two left rotates same as 6 rights rlc ; . . . add c ;Add it to the old bits. ani 3FH ;Turn off the two high order bits. (MOD 64) adi ' ' ;Add a space so the number is printable. mov m,a ;Put in the packet. inx h ;Point to next char. jmp spack7 ;Go store eol character ;Here for 3 character CRC-CCITT spack5: mvi m,0 ;Store a null for current end push h ;Save H lxi h,packet+1 ;Point to first checksumed character call crcclc ;Calculate the CRC pop h ;Restore the pointer mov c,e ;Get low order half for later mov b,d ;Copy the high order mov a,d ;Get the high order portion rlc ;Shift off low 4 bits rlc ; . . . rlc ; . . . rlc ; . . . ani 0FH ;Keep only low 4 bits adi ' ' ;Put into printing range mov m,a ;Store the character inx h ;Point to next position ;Here for two character checksum spack4: mov a,b ;Get high order portion ani 0FH ;Only keep last four bits rlc ;Shift up two bits rlc ; . . . mov b,a ;Copy back into safe place mov a,c ;Get low order half rlc ;Shift high two bits rlc ;to low two bits ani 03H ;Keep only two low bits ora b ;Get high order portion in adi ' ' ;Convert to printing character range mov m,a ;Store the character inx h ;Point to next character mov a,c ;get low order portion ani 3FH ;Keep only six bits adi ' ' ;Convert to printing range mov m,a ;Store it inx h ;Bump the pointer spack7: lda seol ;Get the EOL the other host wants. mov m,a ;Put in the packet. inx h ;Point to next char. xra a ;Get a null. mov m,a ;Put in the packet. ; Write out the packet. outpkt: call selmdm ; Set up for output to comm port if iobyt lda spad ;Get the number of padding chars. sta temp1 outpk2: lda temp1 ;Get the count. dcr a ora a jm outpk6 ;If none left proceed. sta temp1 lda spadch ;Get the padding char. call setpar ;Set parity appropriately mov e,a ;Put the char in right AC. call outmdm ;Output it. jmp outpk2 outpk6: lda dbgflg ora a ; is debugging enabled? jz outpk7 call selcon ; set up for output to console port call sppos ; position cursor lxi h,packet+1 ; print the packet (null-terminated) call dmptxt call selmdm outpk7: lxi h,packet ; Point to the packet. outlup: mov a,m ; Get the next character. ora a ; Is it a null? jz outlud ; If so return success. call setpar ; Set parity for the character mov e,a ; Put it in right AC call outmdm ; and output it. ; TAC trap: If this character is the TAC intercept character, and the TAC ; trap is enabled, we have to output it twice. If the TAC trap is enabled, ; tacflg contains the intercept character. (The current character cannot ; be NUL, so we don't have to worry about doubling nulls in the message) lda tacflg ; get current intercept character, or zero. cmp m ; compare against current data character. jnz outpk8 ; if different, do nothing. call setpar ; match. set appropriate parity, mov e,a ; put it in the right register, call outmdm ; and output it a second time. outpk8: inx h ; Increment the char pointer. jmp outlup outlud: call selcon ; select console jmp rskp ; and return success ; ; Receive_Packet ; This routine waits for a packet to arrive from the host. It reads ; characters until it finds a SOH. It then reads the packet into packet. ; ; Returns: nonskip if failure (checksum wrong or packet trashed) ; skip if success, with ; A - message type ; ARGBLK - message number ; ARGBLK+1 - length of data ; called by: rinit, rfile, rdata, ; sinit, sfile, sdata, seof, seot, finish, logout rpack: call inpkt ;Read up to the end-of-line character jmp r ; Return bad. rpack0: call getchr ;Get a character. jmp rpack ; Hit eol;null line;just start over. cpi soh ;Is the char the start of header char? jnz rpack0 ; No, go until it is. rpack1: call getchr ;Get a character. jmp r ; Hit end of line, return bad. cpi soh  ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sta packet+1 ;Store in packet also mov c,a ;Start the checksum. lda curchk ;Get block check type sui '1' ;Determine extra length of block check mov b,a ;Get a copy mov a,c ;Get back length character sui ' '+3 ;Get the real data count. sub b ;Get total length sta argblk+1 mvi b,0 ;Clear high order half of checksum call getchr ;Get a character. jmp r ; Hit end of line, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sta argblk sta packet+2 ;Save also in packet add c mov c,a ;Add the character to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B lda argblk sui ' ' ;Get the real packet number. sta argblk call getchr ;Get a character. jmp r ; Hit end of line, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sta temp1 ;Save the message type. sta packet+3 ;Save in packet add c mov c,a ;Add the character to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B lda argblk+1 ;Get the number of data characters. sta temp2 lxi h,data ;Point to the data buffer. shld datptr rpack2: lda temp2 sui 1 ;Any data characters? jm rpack3 ; If not go get the checksum. sta temp2 call getchr ;Get a character. jmp r ; Hit end of line, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. lhld datptr mov m,a ;Put the char into the packet. inx h ;Point to the next character. shld datptr add c mov c,a ;Add the character to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B jmp rpack2 ;Go get another. rpack3: call getchr ;Get a character. jmp r ; Hit end of line, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sui ' ' ;Turn the char back into a number. sta temp3 ;Determine type of checksum lda curchk ;Get the current checksum type cpi '2' ;1, 2 or 3 character? jz rpack4 ;If zero, 2 character jnc rpack5 ;Go handle 3 character mov a,c ;Get the character total. ani 0C0H ;Turn off all but the two high order bits. ;Shift them into the low order position. rlc ;Two left rotates same as six rights rlc ; . . . add c ;Add it to the old bits. ani 3FH ;Turn off the two high order bits. (MOD 64) mov b,a lda temp3 ;Get the real received checksum. cmp b ;Are they equal? jz rpack7 ;If so, proceed. rpack9: call updrtr ;If not, update the number of retries. ret ;Return error. ;Here for three character CRC-CCITT rpack5: lhld datptr ;Get the address of the data mvi m,0 ;Store a zero in the buffer to terminate packet lxi h,packet+1 ;Point at start of checksummed region call crcclc ;Calculate the CRC mov c,e ;Save low order half for later mov b,d ;Also copy high order mov a,d ;Get high byte rlc ;Want high four bits rlc ; . . . rlc ;And shift two more rlc ; . . . ani 0FH ;Keep only 4 bits mov d,a ;Back into D lda temp3 ;Get first value back cmp d ;Correct? jnz rpack9 ;No, punt call getchr ;Get a character. jmp r ; Hit end of line, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sui ' ' ;Remove space offset sta temp3 ;Store for later check ;... ;Here for a two character checksum and last two characters of CRC rpack4: mov a,b ;Get high order portion ani 0FH ;Only four bits rlc ;Shift up two bits rlc ; . . . mov b,a ;Save back in B mov a,c ;Get low order rlc ;move two high bits to low bits rlc ; . . . ani 03H ;Save only low two bits ora b ;Get other 4 bits mov b,a ;Save back in B lda temp3 ;Get this portion of checksum cmp b ;Check first half jnz rpack9 ;If bad, go give up call getchr ;Get a character. jmp r ; Hit end of line, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sui ' ' ;Remove space offset mov b,a ;Save in safe place mov a,c ;Get low 8 bits of checksum ani 3FH ;Keep only 6 bits cmp b ;Correct value jnz rpack9 ;Bad, give up rpack7: lhld datptr mvi m,0 ;Put a null at the end of the data. lda temp1 ;Get the type. jmp rskp ; ; inpkt - receive and buffer packet ; returns: nonskip if error (timeout) ; skip if success; packet starts at recpkt (which holds the SOH) ; and is terminated by a carraige return. ; called by: rpack inpkt: lxi h,recpkt ;Point to the beginning of the packet. shld pktptr inpkt1: call inchr ;Get first character jmp r ;Return failure cpi soh ;is it the beginning of a packet? jnz inpkt1 ;if not, ignore leading junk jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a new beginning of packet? jnz inpkt3 ;if not continue lxi h,recpkt ;else throw away what we've got so far shld pktptr ; inpkt3: lhld pktptr ; mov m,a ;Put the char in the packet. inx h shld pktptr mov b,a lxi d,-recpkx ;Start over if packet buffer overflow dad d ; jc inpkt ; lda reol ;Get the EOL char. cmp b jnz inpkt2 ;If not loop for another. ;... ;Begin IBM change/fdc ;This moved from OUTPK7 -- it appears that waiting until we're ;ready to send a packet before looking for turnaround character ;is long enough for it to get lost. Better to look now. lda ibmflg ;Is this the IBM? ora a jz inpkt6 ;If not then proceed. lda state ;Check if this is the Send-Init packet. cpi 'S' jz inpkt6 ;If so don't wait for the XON. inpkt5: call inchr ;Wait for the turn around char. jmp inpkt6 cpi xon ;Is it the IBM turn around character? jnz inpkt5 ;If not, go until it is. inpkt6: lhld pktptr ;Reload packet pointer ;End IBM change/fdc. dcx h ;Back up to end of line character mvi m,0 ;Replace it with a null to stop rpack: lda dbgflg ; Is debugging enabled? ora a jz inpkt7 inx h ; Point to next char. call selcon ; select console to dump packet call rppos ; position cursor lxi h,recpkt+1 ; print the packet call dmptxt call selmdm ; select modem again inpkt7: lxi h,recpkt shld pktptr ;Save the packet pointer. jmp rskp ;If so we are done. ; getchr - get next character from buffered packet. ; returns nonskip at end of packet. ; called by: rpack getchr: lhld pktptr ;Get the packet pointer. mov a,m ;Get the char. inx h shld pktptr ora a ;Is it the null we put at the end of the packet? jnz rskp ;If not return retskp. ret ;If so return failure. ; ; ; inchr - character input loop for file transfer ; returns: nonskip if timeout or character typed on console ; (console selected) ; skip with character from modem in A (parity stripped ; if necessary; modem selected) ; preserves bc, de, hl in either case. ; called by: inpkt inchr: push h ; save hl and bc push b lhld timout ;Get initial value for timeout shld timval ;[jd] inchr0: call selmdm ;select modem call inpmdm ;Try to get a character from the modem ora a jz inchr2 ;if zero, nothing there. mov b,a lda parity ;Is the parity none? cpi parnon mov a,b jz inchr1 ;If so just return. ani 7FH ;Turn off the parity bit. inchr1: pop b ;restore registers pop h jmp rskp ;take skip return, character in A inchr2: call selcon ;select console call inpcon ; Try to get a character from the console ora a jz inchr6 ;If not go do timer thing cpi cr ;Is it a carriage return? jz inchr4 ;If so return cpi ('Z'-100O) ;Control-Z? jz inchr5 ;Yes, go flag it cpi ('C'-100O) ;Control-C? jz kermit ;re-enter, he wants to get out cpi ('X'-100O) ;Control-X? jnz inchr6 ;No, ignore it. do timer thing. inchr5: adi 100O ;Convert to printing range sta czseen ;Flag we saw a control-Z inchr4: pop b ; restore registers pop h ret ;And return inchr6: lda timflg ;[jd] pick up timer flag ora a ;[jd] are we allowed to use timer? jz inchr0 ;[jd] no, don't time out lhld timval ; decrement fuzzy time-out dcx h ; shld timval ;((timout-1) * loop time) mov a,h ;(Retry if not time-out) ora l ; jnz inchr0 ; call updrtr ;Count as retry (?) pop b ;restore registers pop h ret ;and return to do retry ; ; CRCCLC - Routine to calculate a CRC-CCITT for a string. ; ; This routine will calculate a CRC using the CCITT polynomial for ; a string. ; ; call with: HL/ Address of null-terminated string ; 16-bit CRC value is returned in DE. ; Registers BC and HL are preserved. ; ; called by: spack, rpack crcclc: push h ;Save HL push b ;And BC lxi d,0 ;Initial CRC value is 0 crccl0: mov a,m ;Get a character ora a ;Check if zero jz crccl1 ;If so, all done push h ;Save the pointer xra e ;Add in with previous value mov e,a ;Get a copy ani 0FH ;Get last 4 bits of combined value mov c,a ;Get into C mvi b,0 ;And make high order zero lxi h,crctb2 ;Point at low order table dad b ;Point to correct entry dad b ; . . . push h ;Save the address mov a,e ;Get combined value back again rrc ;Shift over to make index rrc ; . . . rrc ; . . . ani 1EH ;Keep only 4 bits mov c,a ;Set up to offset table lxi h,crctab ;Point at high order table dad b ;Correct entry mov a,m ;Get low order portion of entry xra d ;XOR with previous high order half inx h ;Point to high order byte mov d,m ;Get into D pop h ;Get back pointer to other table entry xra m ;Include with new high order half mov e,a ;Copy new low order portion inx h ;Point to other portion mov a,m ;Get the other portion of the table entry xra d ;Include with other high order portion mov d,a ;Move back into D pop h ;And H inx h ;Point to next character jmp crccl0 ;Go get next character crccl1: pop b ;Restore B pop h ;And HL  ret ;And return, DE=CRC-CCITT CRCTAB: DW 00000H DW 01081H DW 02102H DW 03183H DW 04204H DW 05285H DW 06306H DW 07387H DW 08408H DW 09489H DW 0A50AH DW 0B58BH DW 0C60CH DW 0D68DH DW 0E70EH DW 0F78FH CRCTB2: DW 00000H DW 01189H DW 02312H DW 0329BH DW 04624H DW 057ADH DW 06536H DW 074BFH DW 08C48H DW 09DC1H DW 0AF5AH DW 0BED3H DW 0CA6CH DW 0DBE5H DW 0E97EH DW 0F8F7H ; ; This is where we go if we get an error during a protocol communication. ; error prints the error packet on line 6 or so, and aborts the ; transfer. ; called by: rinit, rfile, rdata, sinit, sfile, sdata, seof, seot ; error1 print CRLF followed by the error packet. ; called by: finish, logout ; error2 just prints the error packet. ; error3 positions cursor and prints error message specified in DE. ; called by: rinit, rfile, rdata, send, sinit, sfile, sdata, seof, ; seot, parwrn, gofil, outbuf error: call screrr ;Position the cursor. mvi a,'A' ;Set the state to abort. sta state jmp error2 error1: lxi d,crlf ;Print a CRLF. call prtstr error2: lda argblk+1 ;Get the length of the data. mov c,a mvi b,0 ;Put it into BC lxi h,data ;Get the address of the data. dad b ;Get to the end of the string. mvi a,'$' ;Put a dollar sign at the end. mov m,a lxi d,data ;Print error message call prtstr ret error3: push d ;Save the pointer to the message. call screrr ;Position the cursor. call clrlin ;Clear the line pop d ;Get the pointer back. call prtstr ;Print error message ret ; ; Set up the screen for file transfer. ; called by read, send. init: lxi d,version ; point at Kermit's version string call sysscr ; fix up screen ret ; Set state to ABORT ; called by: rinit, rfile, rdata, sinit, sfile, sdata, seof, seot, ; nak, ackp abort: mvi a,'A' ;Otherwise abort. sta state ret ; nak - send NAK packet ; here from: rinit, rfile, rdata ; nak0 - update retry count and send NAK packet ; here from: rinit, rfile, rdata, tryagn nak0: call updrtr ;Update number of retries. nak: lda pktnum ;Get the packet number we're waiting for. sta argblk xra a ;No data. sta argblk+1 mvi a,'N' ;NAK that packet. call spack jmp abort ; Give up. ret ;Go around again. ; increment and display retry count ; called by: rfile, sinit, sfile, sdata, seof, seot, ; nak, rpack, inchr, tryagn updrtr: call scrnrt ;Position cursor lhld numrtr inx h ;Increment the number of retries shld numrtr call nout ;Write the number of retries. ret ; [jd] this routine prints parity warnings. All registers are ; saved except for a. ; called by: sdata parwrn: push b push d push h lxi d,inms25 call error3 pop h pop d pop b ret ;[jd] end of addition ; print message in status field. address of message is in DE. ; called by: read, send finmes: push d ;Save message. call scrst ;Position cursor pop d ;Print the termination message call prtstr call scrend ;Position cursor for prompt ret ; Compare expected packet number against received packet number. ; return with flags set (Z = packet number valid) ; called by: rfile, rdata, sinit, sfile, sdata, seof, seot compp: lda pktnum ;Get the packet Nr. mov b,a lda argblk cmp b ret ; Increment the packet number, modulo 64. ; called by: rinit, rfile, rdata, sinit, sfile, sdata, seof, seot countp: inr a ;Increment packet Nr. ani 3FH ;Turn off the two high order bits sta pktnum ;Save modulo 64 of number lhld numpkt inx h ;Increment Nr. of packets shld numpkt ret ; Send an ACK-packet ; called by: rfile, rdata, tryagn ackp: xra a sta numtry ;Reset number of retries sta argblk+1 ;No data. (The packet number is in argblk) mvi a,'Y' ;Acknowledge packet call spack ;Send packet jmp abort ret ; ? ; called with A/ current retry count ; called by: rfile, rdata tryagn: inr a ;Increment it. sta oldtry ;Save the updated number of tries. lda pktnum ;Get the present packet number. dcr a ;Decrement ani 3FH ; modulo 64 mov b,a lda argblk ;Get the packet's number cmp b ;Is the packet's number one less than now? jnz nak0 ;No, NAK it and try again. call updrtr ;Update the number of retries. call ackp ret ; Output a null-terminated string to the console. We assume that the ; console has been selected. Called with HL = address of string. ; called by: spack, inpkt dmptxt: mov a,m ; get character from string ora a rz ; done if null push h ; save string address mov e,a ; move character to E for outcon call outcon ; output character to console pop h ; restore string address inx h ; point past printed character jmp dmptxt ; go output rest of string ; IF lasm LINK CP4TT ENDIF;lasm  jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a; CP4TT.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; This file contains the code for the TRANSMIT and CONNECT commands, ; which communicate with a host which is not running KERMIT. ; ; revision history: ; edit 3: July 27, 1984 ; Allow assembly with LASM: to CP4TT is linked by CP4PKT, and links ; to CP4CPM; remove exclamation points so as not to confuse LASM. ; Add Toad Hall TACtrap to TRANSMIT command (TAC intercept character ; is only doubled if it's data; when typed by the user, they're not ; automatically doubled) ; ; edit 2: June 7, 1984 ; formatting and documentation; add module version number; make sure ; console is selected when leaving intchr. ; ; edit 1: May, 1984 ; extracted from CPMBASE.M80 version 3.9; modifications are described ; in the accompanying .UPD file. ttver: db 'CP4TT.ASM (3) 27-Jul-84$' ; This is the TRANSMIT command. It attempts to send a file, even ; though there is no KERMIT on the other side. ; here from: kermit xmit: mvi a,cmofi ;Parse an input file spec (non-wild). lxi d,fcb ;Give the address for the FCB. call comnd jmp kermit ;Give up on bad parse. call cfmcmd call getfil ;Open file. cpi 0FFH ;Succeed? jnz xmit1 lxi d,erms15 call prtstr ;Display error msg. jmp kermit xmit1: lxi d,inms19 ;Output start message. call prtstr call escpr ;Print the escape character. lxi d,inms20 ;Output 2nd part. call prtstr call escpr ;Print the escape character. lxi d,inms21 ;Print the rest. call prtstr mvi a,1 ;Start file I/O. sta fileio xra a ;Clear XOFF flag. sta xofflg ; fall through into xnext... ; ; assemble another line from the disk file. ; here from: previous page, rexmit xnext: call prtchr ; Copy characters from comm line to console mvi c,consta ; until user types anything on the console. call bdos ora a jz xnext ; nothing at console yet. lda eoflag ;EOF encountered? ora a jnz xend ;Yes, finish. xra a ;Reset line buffer counter. mov c,a sta cmaflg ;Reset carriage return flag. lxi d,cmdbuf ;Use comnd buffer as line buffer. lhld bufpnt ; Get current buffer pointer. lda chrcnt ; Get current byte count mov b,a ; in B xmit30: dcr b ; Assume there's a character there jp xmit2 ; If there was, proceed. call inbuf ; There wasn't. Try for another buffer. jmp xmit38 ; End of file. lhld bufpnt ; Got another buffer. Get new pointer in HL lda chrcnt ; and new byte count mov b,a ; in B xmit2: mov a,m ;Get a character from disk buffer. inx h ani 7FH ;Mask 7 bits. jz xmit30 ;Skip nulls. cpi cr ;Carriage return? jz xmit32 cpi subt ;CTRL-Z (substitute)? jz xmit37 cpi lf ;Line feed? jz xmit39 stax d ;Save to buffer. inx d lda cmaflg ;Carriage return seen? ora a jnz xmit31 ;Yes, don't count this character. inr c ;Count it. xmit31: jmp xmit30 ;Loop for next input byte. ; Carriage return seen. Start discarding characters until we see a line-feed. xmit32: sta cmaflg ;Mark return seen. jmp xmit30 ;And continue. ; Control-Z seen. Force end of file, and send the current line. xmit37: sta eoflag ;Mark EOF for next line. ; fall through... ; End of File encountered. eoflag has already been set; just send current line. xmit38: ; fall through... ; Linefeed seen. send the current line. xmit39: shld bufpnt ;Save next buffer pointer. mov a,b ;Save count of remaining characters. sta chrcnt mov a,c ;Save line length. sta filcnt ; fall through into rexmit... ; ; transmit the buffered line. ; here from: previous page, intchr rexmit: lda filcnt ;Set up line length. sta cmccnt lxi h,cmdbuf ;Set up line buffer pointer. shld cmcptr xmit40: call prtchr ;Receive comm. line & display. lda xofflg ;XOFF received? ora a jnz xmit40 ;Yes, wait for XON lda cmccnt ;Any characters left? dcr a jm xmit49 ;No, next state. sta cmccnt call selmdm ; select modem for outmdm lhld cmcptr ;Get the character to be sent mov a,m inx h ;Bump to next character. shld cmcptr call setpar ;Set parity (if any). mov e,a ;Save character (with parity) call outmdm ;Output it to the comm. line. ; TAC trap: If this character is the TAC intercept character, and the TAC ; trap is enabled, we have to output it twice. If the TAC trap is enabled, ; tacflg contains the intercept character. (The current character cannot ; be NUL, so we don't have to worry about doubling nulls in the message) lda tacflg ; get current intercept character, or zero. cmp m ; compare against current data character. jnz xmit41 ; if different, do nothing. call setpar ; match. set appropriate parity, mov e,a ; put it in the right register, call outmdm ; and output it a second time. xmit41: lda ecoflg ;Local echo? ora a jz xmit40 ;No, continue. mov a,e ;Get the character. ani 7FH ;Mask out parity. mov e,a ;Display on console. call selcon call outcon jmp xmit40 ;Continue. xmit49: xra a ;Reset last character seen. sta lstchr xmit50: call prtchr ;Receive comm. line & display. call conchr ;Read keyboard & send. jmp xendc ;CLOSE connection. lda lstchr ;Check last keyboard character. cpi cr ;Carriage return? jz xnext ;Yes, prepare to send next line. jmp xmit50 ;Continue, until carriage return. ; ; clean up. ; xend - end of file reached. close file, go to connect mode. ; here from: xnext. ; xendc - user wants out. close file, go to command mode. ; here from: rexmit. xend: call xmtoff ;Close file, etc. lxi d,inms22 ;Tell we're done with transmission jmp telnt1 ;Branch to CONNECT command. xendc: call xmtoff ;Close file, etc. jmp kermit ;Back to command loop. xmtoff: mvi c,closf ;Close file. lxi d,fcb call bdos xra a ;Terminate file I/O. sta fileio ret ; ; telnet - the CONNECT command. ; here from: kermit ; telnt1 - entry to connect mode from TRANSMIT command ; here from: xend telnet: call cfmcmd lxi d,infms7 ;Output start of message ; enter here from TRANSMIT command. telnt1: call prtstr call escpr ;Print the escape char. lxi d,infms8 ;Output some more of the message call prtstr call escpr ;Print the escape char again. lxi d,inms8a ;Print the remainder of the message call prtstr call syscon ;do system-dependent stuff chrlup: call prtchr ;See if char at port (send to console). call conchr ;See if char at console (send to port). jmp kermit ;requested to end session - go to command loop. jmp chrlup ;Go do it again. ; ; ; prtchr - copy characters from comm line to console ; returns: nonskip, console selected. ; called by: xnext, rexmit, telnet ; prtchr: call selmdm ; select modem port call inpmdm ; try to get a character from it ora a ; test character jnz prtch0 ; if non-zero, process it. call selcon ; select console ret ; return. prtch0: ani 7FH ; drop parity bit. jz prtchr ; ignore null (filler) cpi del ; ignore delete, too jz prtchr cpi xon ;Is it an XON? jz prtxon ;yes cpi xoff ;Is it an XOFF? jz prtxof ;yes mov e,a ;Set the char aside. lda vtflg ;Get the VT52 emulation flag. cpi 1 ;Is the flag set? jnz prtch1 ;If not, don't do this stuff. lda escflg ;Get the escape flag. ora a ;Are we working on an escape sequence? jz prtch2 ;If not, continue. call vt52 ;If so, work on it some more jmp prtchr ;try for more characters. prtch2: mov a,e ;normal text. cpi esc ;Is the char an escape? jnz prtch1 ;If not skip on. mvi a,1 sta escflg ;Set the escape flag: escape seen. jmp prtchr ;Get another char... prtch1: call sysflt ; ok to print this character (in E)? ora a jz prtchr ; no, skip it. lda logflg ;Get the log flag. ora a cnz logit ;Log the char if it is set. call selcon ; select console lda prnflg ;Get Print parallel flag ora a cnz outlpt ; output to printer if flag set call outcon ; output to console. jmp prtchr ; go around again. ; I don't think we want to print xon/xoff - this should be ; flow control only across the link between us and the host. ; (besides, IBM host xon's don't make sense to most micros) ; remember xon/xoff state in xofflg (zero = xon, non-zero = xoff) prtxon: xra a ;Yes, reset XOFF flag prtxof: sta xofflg jmp prtchr ; look for another character ; ; ; logit - output character in E to log file. ; we assume the host recognizes xon/xoff. (we probably shouldn't) ; modem port is selected. ; preserves de ; called by: prtchr logit: lhld bufpnt mov m,e ;Store the char. inx h shld bufpnt mov a,l ora a ;Buffer full? rnz push d mvi a,xoff ;^S to stop the host while we write the buffer. call setpar ; set correct parity... mov e,a call outmdm ; output it. mvi c,writef lxi d,fcb call bdos ora a ;Successful. jz logit2 lxi d,erms11 call prtstr logit2: mvi a,xon ;^Q to restart the host call setpar ; set appropriate parity mov e,a call outmdm ; send it. lxi h,buff shld bufpnt ;Reset the buffer pointer. pop d ret ; ; ; VT52 emulation. ; called by: prtchr ; A/ contents of escflg (guaranteed non-zero) ; E/ current character ; modem is selected. ; vt52: cpi 1 ; first character after escape? jnz vt52y ; no, must be doing cursor positioning. ; ; E contains the character that followed the escape. ; valid characters are: ; A - cursor up ; B - cursor down ; C - cursor right ; D - cursor left ; F - enter graphics mode (hard to do on a non-vt52) ; G - exit graphics mode ; H - home ; I - reverse linefeed ; J - erase to end of screen ; K - erase to end of line ; Y - cursor positioning leadin ; Z - identify terminal as VT52 ; [ - enter hold-screen mode (not supported) ; \ - exit hold-screen mode (not supported) ; > - enter alternate-keypad mode? (not supported) ; = - exit alternate-keypad mode? (not supported) ; ; Invalid sequences are handled as the VT52 does - the escape and ; the following character are swallowed, never to be seen again. ; For E, the translation table may contain just '$' (no action), ; or may be used as clear-and-home, as in the Heath/Zenith H19. ; mov a,e ; get the second character of the sequence. cpi 'Y' ; if cursor lead-in handle it. jnz vt52a ; if not, go on. mvi a,2 ; state = 2: row follows. sta escflg ; update the flag. ret ; back for another character vt52a: cpi 'Z' ; VT52 ID query? jz vt52id ; yes. claim to be one. cpi 'A' ;Less than an 'A'? jm vtig ;Yes - ignore. cpi 'K'+1 ;Greater than 'K'? jp vtig ;Yes - ignore. sui 'A' ;Else make into index. rlc ;Multiply by four. rlc ;(Shift left twice.) lhld pttab ;Load base addr of table. mov e,a ;Move a into de pair. mvi d,00H ;Zero out high byte. dad d ;Double add index+offset. xchg ;Exchange de with hl. call selcon ; select console call prtstr ;and syscall. vtig: ;Ignore escape sequence. xra a ;Reset the ol' escape flag. sta escflg ret ;Return home. ; here for Z. Tell the host we're a VT52. (Sure we are...) vt52id: mvi a,esc ; response is escape... call setpar ; (need correct parity) mov e,a call outmdm ; (console already selected) mvi a,'/' ; ... slash ... call setpar ; (with parity) mov e,a call outmdm mvi a,'K' ; ... K. call setpar mov e,a call outmdm jmp vtig ; clear escape-sequence flag and return. ; here when escflg isn't 0 or 1 - processing cursor positioning sequence. vt52y: cpi 2 ; looking for row? (y-coordinate) jnz vt52x ; no, must be column. mov a,e ; yes. get coordinate sui (' '-1) ; convert from ascii (1 = top line) sta vtyval ; store for later mvi a,3 ; advance to next state (x coord) sta escflg ; store it ret ; try for another character ; here when escflag isn't 0, 1, or 2 - it must be 3. (right?) ; E holds the last character of the cursor positioning sequence. vt52x: xra a ; end of escape sequence, reset state. sta escflg mov a,e ; get column (' ' is left margin) sui (' '-1) ; make left margin be one mov c,a ; stash column in c lda vtyval ; get row number mov b,a ; in b call selcon ; select console call csrpos ; call system-dependent cursor positioner ret ; all through. ; ; ; conchr - copy character from console to comm line, processing ; (kermit's) escape sequences. ; Enter and exit with console selected. ; nonskip return: transparent mode terminated. ; skip return: still in transparent mode. ; called by: rexmit, telnet conchr: call inpcon ;Try to get a character from the console ani 07FH ;Keep only 7 bits jz rskp ;Null means nothing there. mov e,a ;Move the char for comparison. sta lstchr ;Save it lda escchr ;Get the escape char. cmp e ;Is it an escape char? jz intchr ;If so go process it. call selmdm ; select the modem mov a,e ;Get the char. call setpar ;Set parity (if any). mov e,a ;Restore it. call outmdm ;Output the char to the port. call selcon ; reselect console lda ecoflg ;Get the echo flag. ora a ;Is it turned on? jz rskp ;If not we're done here. mov a,e ;Get the char. ani 7FH ;Turn off the parity bit. mov e,a call outcon ; echo the character. jmp rskp ; use skip return ; ; transparent escape character has been typed. dispatch on second ; character. (console is still selected) ; here from: conchr intchr: call inpcon ; get another character from the console ora a ; zero means no character available yet. jz intchr ; If so, loop until we get a char. mov b,a ;Save the actual char. cpi ctrlc ;is it Control-C? jz contc ;yes ani 137O ;Convert to upper case. cpi 'C' ;Is it close? jnz intch0 ;If not proceed. contc: lxi d,infms9 ;Say we are back. call prtstr call syscls ; call system-dependent close routine lda logflg ;Get the log flag. ora a ;Is it set? rz ;Return if it is zero. xra a sta logflg ;Turn off the log flag. lxi d,infms6 ;Tell user we are closing file. call prtstr lhld bufpnt mvi m,('Z'-100O) ;Put in a ^Z. mvi c,writef ;Write the last buffer. lxi d,fcb call bdos mvi c,closf ;Close the file. lxi d,fcb call bdos ret ;Here if not a 'C' or '^C' intch0: cpi 'S' ;Is it status? jnz inch01 ;If not, proceed. call stat01 ;Print out the status stuff. jmp rskp ;return from conchr inch01: cpi 'R'-100O ;Control-R? jz inch02 ;Yes cpi 'R' ;(plain) R? jnz inch03 ;No inch02: lda fileio ;TRANSMIT in progress? ora a jz inch03 ;No,ignore pop b ;Remove return address (non-local goto) jmp rexmit ;Retransmit line inch03: mov a,b ;Get the char. cpi '?' ;Is it a help request? jnz intch1 ;If not, go to the next check. lda fileio ;TRANSMIT in progress? ora a jz inch04 ;No lxi d,xmthlp ;Tell about R too call prtstr inch04: lxi d,inthlp ;If so, get the address of the help message. call prtstr call sysinh ; print system-dependent help message lxi d,inhlp1 ; Tell about doubling the escape character call prtstr call escpr ;Print escape character lxi d,inhlp2 ;Print the rest call prtstr jmp intchr ;Get another char. intch1: mov a,b ;Get the character. cpi '0' ;Is it '0', to send a null? jnz intch3 ;No. xra a ;Yes, send an ASCII zero. call setpar ; with the correct parity mov e,a call selmdm ; (to the modem...) call outmdm call selcon ; return with console selected jmp rskp intch3: lda escchr ;Get the escape char. cmp b ;Is it the escape char? jnz intchz ;If not, look for local additions mov a,b ;Get the char. call setpar mov e,a ;Restore it. call selmdm call outmdm ;Output it. call selcon ;We promised console would be selected... jmp rskp ;Return, we are done here. intchz: mov a,b ; not recognized. get saved copy back. call sysint ; interpret system-dependent sequences jmp rskp ; done. return (from conchr). mvi e,'G'-100O ;Otherwise send a beep. call outcon ; to the console. jmp rskp ; IF lasm LINK CP4CPM ENDIF;lasm  = address of string. ; called by: spack, inpkt dmptxt: mov a,m ; get character from string ora a rz ; done if null push h ; save string address mov e,a ; move character to E for outcon call outcon ; output character to console pop h ; restore string address inx h ; point past printed character jmp dmptxt ; go output rest of string ; IF lasm LINK CP4TT ENDIF;lasm  jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a; CP4UTL.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; Utility routines, pure and impure data. ; ; revision history: ; edit 2: August 3, 1984 ; move "mover" to CP4SYS to allow use of Z80 block move instruction. ; ; edit 1: July 27, 1984 ; extracted from CP4MIT.M80 edit 2, as part of LASM support. This is ; the last file linked for the system-independent code. ; utlver: db 'CP4UTL.ASM (2) 3-Aug-84$' ; Set the parity for a character in A. ; called by: spack, rexmit, logit, vt52, conchr, intchr setpar: push h ;Save HL.  push b lxi h,parity mov c,m ;Get the parity routine. mvi b,0 lxi h,parjmp ;Get the first address. dad b pchl parjmp: jmp even jmp mark jmp none jmp odd jmp space none: jmp parret ;Don't touch the parity bit. even: ani 7FH ;Strip parity. jpe parret ;Already even, leave it. ori 80H ;Make it even parity. jmp parret mark: ori 80H ;Turn on the parity bit. jmp parret odd: ani 7FH ;Strip parity. jpo parret ;Already odd, leave it. ori 80H ;Make it odd parity. jmp parret space: ani 7FH ;Turn off the parity bit. jmp parret parret: pop b pop h ;Restore HL. ret ; ; Print the escape char. ; called by: stat01, xmit, telnet, intchr escpr: lda escchr ;Get the escape char. cpi ' ' ;Is it a control char? jp escpr2 lxi d,inms10 ;Output "Control-". call prtstr lda escchr ori 100O ;De-controlify. escpr2: mvi c,conout ;Output the char mov e,a call bdos ret ; fetch keyword; if unsuccessful, return to command level. ; called by: kermit, setcom keycmd: mvi a,cmkey call comnd jmp keycm2 ;no match ret keycm2: lxi d,ermes1 ;"Unrecognized Command" call prtstr jmp kermit ;Do it again. ; request confirmation; if unsuccessful, return to command level ; called by: bye, exit, help, log, setcom, show, status, send, ; finish, logout, xmit, telnet cfmcmd: mvi a,cmcfm call comnd jmp kermt3 ;"Not confirmed" ret ; ; This routine prints the number in HL on the screen in decimal. ; Uses all ACs. ; called by: cp4sys, read, send, updrtr, dir nout: lxi b,-10 ;Get some useful constants. nout1: lxi d,-1 nout2: dad b ;Subtract as many 10s as possible. inx d ;Count them. jc nout2 ;If some left keep going. push h ;save remainder - 10 xchg ;Swap the remainder and the quotient. mov a,h ;Get the number of 10s found. ora l ;check for quotient non zero cnz nout1 ;If non zero, recurse. pop h ;Get the remainder - 10 mov a,l ;in a adi '0'+10 ;Make the number printable and add the 10 back mov e,a ;Output the digit. mvi c,conout jmp bdos ; prcrlf - print a CR/LF. (Saves no registers.) [Toad Hall] ; prtstr - print string pointed to by DE ; called by: lots of places. prcrlf: lxi d,crlf ;Point to the CR/LF prtstr: mvi c,prstr ; output string jmp bdos ;a CALL followed by a RET becomes a JMP ; Jumping to this location is like retskp. It assumes the instruction ; after the call is a jmp addr. ; here from: many places. rskp: pop h ;Get the return address. inx h ;Increment by three. inx h inx h pchl ; Jumping here is the same as a ret. 'jmp r' is used after routines ; that have skip returns, where the non-skip instruction must be 3 bytes. ; here from: many places. r: ret ; ; Open a file for reading (with inbuf). The filename is already ; in fcb; upon return, the end of file flag is cleared and chrcnt ; is set to zero, so inbuf will be called to get a buffer when we ; next attempt to get a character. ; called by: sinit, seof, xmit getfil: xra a  sta chrcnt ;Buffer is empty. sta eoflag ;Not the end of file. sta fcb+0CH ;Zero the extent. sta fcb+0EH ;Must be zero for MAKEF or OPENF. sta fcb+20H ;Zero the current record. mvi c,openf ;Open the file. lxi d,fcb call bdos ret ; Get next sector from disk. ; preserves bc, de, hl ; returns nonskip if EOF or error; ; returns skip with chrcnt and bufpnt updated if success. ; called by: gtchr, xnext inbuf: lda eoflag ;Have we reached the end? ora a jz inbufa ;no mvi b,0 rnz ;Return if set. inbufa: push b push d push h lxi h,chrcnt ;Reset character count. mvi m,bufsiz-1 ; (already decremented by one) lxi h,buff ;Set the buffer pointer. shld bufpnt mvi c,readf ;Read a record. lxi d,fcb call bdos ora a ;00H => read O.K jz inbuf4 xra a ;we either hit EOF or an ERROR sta chrcnt ;say no more chars in buffer mvi a,0FFH sta eoflag ;Set the EOF flag. pop h ; restore registers pop d pop b ret ; EOF/error: take non-skip return. inbuf4: pop h ;more data, restore and rskp pop d pop b jmp rskp ; ; output the buffer, reset bufpnt and chrcnt ; called by: rdata, ptchr outbuf: push b mvi c,writef ;The write code. lxi d,fcb call bdos ;Write the record. pop b ora a ;Successful. jz outbf1 lxi d,erms11 call error3 ret outbf1: lxi h,buff ;Addr for beginning. shld bufpnt ;Store addr for beginning. mvi a,bufsiz-1 ;Buffer size. sta chrcnt ;Number of chars left. jmp rskp ; ; Pure storage (well, almost. apparently, little x's don't count). version:db 'Kermit-80 v4.02 $' kerm: db 'Kermit-80 ' kerm1: db 'x:>$' ;'x' filled in at startup with DRIVE name crlf: db cr,lf,'$' ermes1: db cr,lf,'?Unrecognized command$' ermes3: db cr,lf,'?Not confirmed$' ermes4: db '?Unable to receive initiate',cr,lf,'$' ermes5: db '?Unable to receive file name',cr,lf,'$' ermes6: db '?Unable to receive end of file',cr,lf,'$' erms10: db '?Unable to receive data',cr,lf,'$' erms11: db '?Disk full',cr,lf,'$' erms14: db '?Unable to receive an acknowledgement from the host',cr,lf,'$' erms15: db cr,lf,'?Unable to find file',cr,lf,'$' erms16: db '?Unable to rename file$' erms17: db cr,lf,'?Disk full$' erms18: db cr,lf,'?Unable to tell host that the session is finished$' erms19: db cr,lf,'?Unable to tell host to logout$' erms20: db cr,lf,'?Kermit has not been configured for a target system$' erms21: db cr,lf,'?Consistency check on configuration failed$' infms3: db bell,'Completed$' infms4: db bell,'Failed$' infms5: db '%Renaming file to $' infms6: db cr,lf,'[Closing the log file]$' infms7: db cr,lf,'[Connected to remote host. Type $' infms8: db 'C to return;',cr,lf,' type $' inms8a: db '? for command list]',cr,lf,'$' infms9: db cr,lf,'[Connection closed, back at micro]$' inms10: db 'Control-$' inms12: db ' (Not implemented)',cr,lf,'$' inms13: db bell,'Interrupted$' inms14: db TAB,TAB,' Directory for drive ' dnam14: db 'x:',cr,lf,'$' ;filled in by dir routine. inms15: DB CR,LF,TAB,TAB,'Drive $' inms16: DB ' has $';filled in by summary code with drive letter inms17: DB 'K bytes free',CR,LF,'$' inms18: DB CR,LF,'File(s) erased$',CR,LF inms19: db cr,lf,'[Transmitting file to host:' db cr,lf,' 1. Type any character to send a line.' db cr,lf,' 2. Type RETURN to terminate the line ' db 'and to get the next line (go back to 1.)' db cr,lf,' (You may send other characters ' db 'before RETURN.),' db cr,lf,' or type $' inms20: db 'R to send the same line again,' db cr,lf,' or type $' inms21: db 'C to abort transmission.]',cr,lf,'$' inms22: db cr,lf,'[Transmission done. Connected normally ' db 'to remote host,' db cr,lf,' type $' inms23: db 'Sending...$' inms24: db 'Receiving...$' inms25: db bell,'Warning: eighth bit cannot be sent$' inms26: db cr,lf,'For help, type ? at any point in a command$' escmes: db cr,lf,'Type the new escape character: $' tacmes: db cr,lf,'Type the new TAC intercept character: $' ; top-level help message. Caps indicate keywords. (consistency? what's that?) tophlp: db cr,lf,'BYE to host (LOGOUT) and exit to CP/M' db cr,lf,'CONNECT to host on selected port' db cr,lf,'ERA a CP/M file' db cr,lf,'EXIT to CP/M' db cr,lf,'FINISH running Kermit on the host' db cr,lf,'HELP by giving this message' db cr,lf,'DIR of current used Micro-disk' db cr,lf,'LOG the terminal session to a file' db cr,lf,'LOGOUT the host' db cr,lf,'RECEIVE file from host' db cr,lf,'SEND file to host' db cr,lf,'SET a parameter' db cr,lf,'SHOW the parameters' db cr,lf,'STATUS of Kermit' db cr,lf,'TRANSMIT file to host (in connect state)$' ; help message for SET command. Caps indicate minimum abbreviation. sethlp: db cr,lf,'BAud (rate)' db cr,lf,'BLock-check-type (for error detection)' db cr,lf,'DEBug (messages ON / OFF)' db cr,lf,'DEFault-disk (to receive data)' db cr,lf,'Escape (character during CONNECT)' db cr,lf,'File-mode (for outgoing files)' db cr,lf,'Ibm (parity and turn around handling)' db cr,lf,'Local-echo (half-duplex)' db cr,lf,'PArity (for communication line)' db cr,lf,'POrt (to communicate on)' db cr,lf,'PRinter copy ( ON / OFF )' ;* db cr,lf,'Receive (parameter)' ;Not currently implemented ;* db cr,lf,'Send (parameter)' ;Ditto db cr,lf,'TAC Intercept Character TACtrap ( ON / OFf / Character)' db cr,lf,'TImer ( ON / OFf )' db cr,lf,'Vt52-emulation' db cr,lf,'Warning (for filename conflicts)' db '$' stshlp: db cr,lf,'PAD-CHAR' db cr,lf,'PADDING$' blkhlp: db cr,lf,'1-CHARACTER-CHECKSUM' db cr,lf,'2-CHARACTER-CHECKSUM' db cr,lf,'3-CHARACTER-CRC-CCITT$' typhlp: db cr,lf,'ASCII BINARY DEFAULT$' tachlp: db cr,lf,'ON to enable TAC trap' db cr,lf,'OFF to disable TAC trap' db cr,lf,'CHARACTER to enable TAC trap and' db ' specify intercept character$' parhlp: db cr,lf,'EVEN MARK NONE ODD SPACE$' onhlp: db cr,lf,'OFF ON$' xmthlp: db cr,lf,'R Send the same line again$' inthlp: db cr,lf,'? This message' db cr,lf,'C Close the connection' db cr,lf,'0 (zero) Transmit a NULL' db cr,lf,'S Status of the connection$' inhlp1: db cr,lf,'Typing another $' inhlp2: db ' will send it to the host' db cr,lf,cr,lf,'Command>$' xmtst: db cr,lf,'Transmitting a file$' locst: db cr,lf,'Local echo$' onstr: db ' on$' offstr: db ' off$' vtemst: db cr,lf,'VT52 emulation$' cpmst: db cr,lf,'File Mode$' defstr: db ' default$' ascstr: db ' ASCII$' binstr: db ' binary$' ibmst: db cr,lf,'IBM flag$' filst: db cr,lf,'File warning$' prst: db cr,lf,'Printer copy$' escst: db cr,lf,'Escape char: $' bckst: db cr,lf,'Block check type: $' bckst1: db '-character$' parst: db cr,lf,'Parity: $' pnonst: db 'none$' pmrkst: db 'mark$' pspcst: db 'space$' poddst: db 'odd$' pevnst: db 'even$' spdst: db cr,lf,'Speed $' spdust: db 'is indeterminate (not SET)$' timmsg: db 'Timer$' tacst: db cr,lf,'Current TACTrap Status/Intercept Character: $' ; ;COMND tables ; ; Structure of command table: ; ; 1) Number of entries. ; 2) Each entry is arranged as follows: ; a) length of command in bytes. ; b) 'name of command and $-sign' ; c) offset into command table at KERMTB: ; d) offset into command table at KERMTB: ; ; ---> Note this command table is in alphabetic order. ; comtab: db 10H ; 16 entries db 03H,'BYE$', 21H,21H db 07H,'CONNECT$', 00H,00H db 03H,'DIR$', 24H,24H db 03H,'ERA$', 27H,27H db 04H,'EXIT$', 03H,03H db 06H,'FINISH$', 1BH,1BH db 03H,'GET$', 0CH,0CH ;Same as RECEIVE db 04H,'HELP$', 06H,06H db 03H,'LOG$', 09H,09H db 06H,'LOGOUT$', 1EH,1EH db 07H,'RECEIVE$', 0CH,0CH db 04H,'SEND$', 0FH,0FH db 03H,'SET$', 12H,12H db 04H,'SHOW$', 15H,15H db 06H,'STATUS$', 18H,18H db 08H,'TRANSMIT$',2AH,2AH settab: db 15 ; 15 entries [Toad Hall] ;Hex is data keys to SETJTB positions db 04H,'BAUD$', 21H,21H db 10H,'BLOCK-CHECK-TYPE$',18H,18H db 05H,'DEBUG$', 2DH,2DH db 0CH,'DEFAULT-DISK$', 24H,24H db 06H,'ESCAPE$', 00H,00H db 09H,'FILE-MODE$', 12H,12H db 03H,'IBM$', 03H,03H db 0AH,'LOCAL-ECHO$', 06H,06H db 06H,'PARITY$', 15H,15H db 04H,'PORT$', 1EH,1EH db 07H,'PRINTER$', 27H,27H ;* db 07H,'RECEIVE$', 09H,09H ;Not implemented yet. ;* db 04H,'SEND$', 0CH,0CH ;Ditto db 07H,'TACTRAP$', 30H,30H ;Tactrap db 05H,'TIMER$', 2AH,2AH ;[jd] set timer... db 0EH,'VT52-EMULATION$', 1BH,1BH db 07H,'WARNING$', 0FH,0FH stsntb: db 02H ;Two entries. db 08H,'PAD-CHAR$', 00H,00H db 07H,'PADDING$', 03H,03H blktab: db 03H ;Three entries. db 14H,'1-CHARACTER-CHECKSUM$', '1','1' db 14H,'2-CHARACTER-CHECKSUM$', '2','2' db 15H,'3-CHARACTER-CRC-CCITT$', '3','3' partab: db 05H ;Five entries. db 04H,'EVEN$', parevn,parevn db 04H,'MARK$', parmrk,parmrk db 04H,'NONE$', parnon,parnon db 03H,'ODD$', parodd,parodd db 05H,'SPACE$', parspc,parspc ontab: db 02H ;Two entries. db 03H,'OFF$', 00H,00H db 02H,'ON$', 01H,01H typtab: db 03H ;Three entries db 05H,'ASCII$', 01H,01H db 06H,'BINARY$', 02H,02H db 07H,'DEFAULT$', 00H,00H tactab: db 03H ;Three entries. db 09H,'CHARACTER$', 02H,02H db 03H,'OFF$', 00H,00H db 02H,'ON$', 01H,01H cmer00: db cr,lf,'?Program error: Invalid COMND call$' cmer01: db cr,lf,'?Ambiguous$' cmer02: db cr,lf,'?Illegal CP/M file specification$' cmer03: db cr,lf,'?"*" not allowed in file specification$' cmin00: db ' Confirm with carriage return$' ; ;Impure data ;COMND storage cmstat: ds 1 ;What is presently being parsed. cmaflg: ds 1 ;Non-zero when an action char has been found. cmccnt: ds 1 ;Non-zero if a significant char is found. cmsflg: ds 1 ;Non-zero when the last char was a space. cmostp: ds 2 ;Old stack pointer for reparse. cmrprs: ds 2 ;Address to go to on reparse. cmprmp: ds 2 ;Address of prompt. cmptab: ds 2 ;Address of present keyword table. cmhlp: ds 2 ;Address of present help. cmdbuf: ds 80H ;Buffer for command parsing. cmfcb: ds 2 ;Pointer to FCB. cmfcb2: ds 2 ;Pointer to position in FCB. cmfwld: ds 1 ;Wildcard flag cmcptr: ds 2 ;Pointer for next char input. cmdptr: ds 2 ;Pointer into the command buffer. cmkptr: ds 2 ;Pointer to keyword. cmsptr: ds 2 ;Place to save a pointer. ; oldsp: ds 2 ;Room for old system stack. ds 40H ;Room for 32 levels of calls. stack: ds 2 eoflag: ds 1 ;EOF flag;non-zero on EOF. curdsk: db 0 ;holds "logged" disk prnflg: db 0 ;Flag copy to printer timflg: db 0 ;[jd] timer flag: 0 -> no timer timval: dw 0 ;[jd] timer value wrn8: db 0 ;[jd] non-zero if 8-bit-lost warning sent qbchr: db '&' ;[jd] binary quote character. quot8: db 0 ;[jd] non-zero if doing 8-bit quoting logflg: db 0 ;Flag for a log file. escflg: db 0 ;Escape flag (start off). fileio: db 0 ;Line-by-line from file (default off). xofflg: db 0 ;X-OFF (=^S) received from COMM-line ; ;X-ON (=^Q) received resets this vtyval: ds 1 ; holds row number for VT52 cursor positioning chrcnt: ds 1 ;Number of chars in the file buffer. filcnt: ds 1 ;Number of chars left to fill. outpnt: ds 2 ;Position in packet. bufpnt: ds 2 ;Position in file buffer. fcbptr: ds 2 ;Position in FCB. datptr: ds 2 ;Position in packet data buffer. cbfptr: ds 2 ;Position in character buffer. pktptr: ds 2 ;Position in receive packet. size: ds 1 ;Size of data from gtchr. curchk: ds 1 ;Current checksum type inichk: ds 1 ;Agreed upon checksum type czseen: ds 1 ;Flag that control-Z was typed pktnum: ds 1 ;Packet number. numpkt: ds 2 ;Total number of packets sent. numrtr: ds 2 ;Total number of retries. numtry: ds 1 ;Number of tries on this packet. oldtry: ds 1 ;Number of tries on previous packet. state: ds 1 ;Present state of the automaton. packet: ds 4 ;Packet (data is part of it). data: ds 5AH ;Data and checksum field of packet. recpkt: ds 65H ;Receive packet storage (use the following). recpkx: db cr,'$' ;= = = buffer limit filbuf: ds 65H ;Character buffer. fnbuf: ds 20h ;[jd] file name buffer ;** Temp 1 & 2 must be in order temp1: ds 1 ;Temporary storage. lstchr EQU temp1 ;Last console input character. temp2: ds 1 temp3: ds 1 temp4: ds 1 argblk: ds 20H ;Used for subroutine arguments maxfil EQU 2 ; currently, only two names used. fcbblk: ds maxfil*10H ;Used for a list of FCB's patch: ds 100 ; Guarantee some patch space ORG ($ + 0ffH) AND 0ff00H ; move to start of next page ; ; hooks for system-dependent routines: ; This area is overwritten by the system-dependent overlay. ; lnkflg: dw 0 ; linkage information for consistency check. lnkent: dw 0 ; more of the same. dw 0 ; I'll think of something to do with this later. ; ; Input/output routines. Note that outmdm and outcon may actually be the ; same routine if selmdm and selcon do anything. (the same is true ; of inpmdm and inpcon). ; selmdm: jmp $-$ ; select modem for I/O outmdm: jmp $-$ ; output character in E to modem inpmdm: jmp $-$ ; read character from modem. return character or 0 in A. selcon: jmp $-$ ; select console for I/O outcon: jmp $-$ ; output character in E to console inpcon: jmp $-$ ; read char from console. return character or 0 in A outlpt: jmp $-$ ; output character in E to printer ; ; screen formatting routines clrlin: jmp $-$ ; erase current line clrspc: jmp $-$ ; erase current position (after backspace) delchr: jmp $-$ ; make delete look like backspace clrtop: jmp $-$ ; erase screen and go home ; ; these routines are called to display a field on the screen. scrend: jmp $-$ ; move to prompt field screrr: jmp $-$ ; move to error message field scrfln: jmp $-$ ; move to filename field scrnp: jmp $-$ ; move to packet count field scrnrt: jmp $-$ ; move to retry count field scrst: jmp $-$ ; move to status field rppos: jmp $-$ ; move to receive packet field (debug) sppos: jmp $-$ ; move to send packet field (debug) ; sysinit: jmp $-$ ; program initialization sysexit: jmp $-$ ; program termination syscon: jmp $-$ ; remote session initialization syscls: jmp $-$ ; return to local command level sysinh: jmp $-$ ; help text for interrupt (escape) extensions sysint: jmp $-$ ; interrupt (escape) extensions, including break sysflt: jmp $-$ ; filter for incoming characters.  ; called with character in E. sysbye: jmp $-$ ; terminate remote session sysspd: jmp $-$ ; baud rate change routine. ; called with value from table in DE sysprt: jmp $-$ ; port change routine. ; called with value from table in DE sysscr: jmp $-$ ; screen setup for file transfer ; called with Kermit's version string in DE csrpos: jmp $-$ ; move cursor to row B, column C sysspc: jmp $-$ ; calculate free space for current disk mover: jmp $-$ ; block move ; ; Data initialized by system-dependent overlay: ; pttab: ds 2 ; points to local equivalents to VT52 escape sequences spdtab: ds 2 ; address of baud rate command table, or zero spdhlp: ds 2 ; address of baud rate help table, or zero prttab: ds 2 ; address of port command table, or zero prthlp: ds 2 ; address of port help table, or zero timout: ds 2 ; Initial value for fuzzy timeout vtflg: ds 1 ; VT52 emulation flag escchr: ds 1 ; Storage for the escape character. speed: ds 2 ; storage for the baud rate dbgflg: ds 1 ; debugging flag ecoflg: ds 1 ; Local echo flag (default off). flwflg: ds 1 ; File warning flag (default on). ibmflg: ds 1 ; IBM flag (default off). cpmflg: ds 1 ; File mode flag (ascii/binary/default) parity: ds 1 ; Current parity. spsiz: ds 1 ; Send packet size. rpsiz: ds 1 ; Receive packet size. stime: ds 1 ; Send time out. rtime: ds 1 ; Receive time out. spad: ds 1 ; Send padding. rpad: ds 1 ; Receive padding. spadch: ds 1 ; Send padding char. rpadch: ds 1 ; Receive padding char. seol: ds 1 ; Send EOL char. reol: ds 1 ; Receive EOL char. squote: ds 1 ; Send quote char. rquote: ds 1 ; Receive quote char. chktyp: ds 1 ; Checksum type desired tacflg: ds 1 ; TACTrap flag (zero=off, nonzero=on; when non-zero, ; contains current TAC intercept character) tacchr: ds 1 ; TAC intercept character ; space used by directory command; here because space calculation is ; (operating) system-dependent bmax: ds 2 ; highest block number on drive bmask: ds 1 ; (records/block)-1 bshiftf: ds 1 ; number of shifts to multiply by rec/block nnams: ds 1 ; counter for filenames per line lnksiz equ $-lnkflg ; length of linkage section, for consistency check. END START 4CPM ENDIF;lasm  = address of string. ; called by: spack, inpkt dmptxt: mov a,m ; get character from string ora a rz ; done if null push h ; save string address mov e,a ; move character to E for outcon call outcon ; output character to console pop h ; restore string address inx h ; point past printed character jmp dmptxt ; go output rest of string ; IF lasm LINK CP4TT ENDIF;lasm  jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a; CP4WLD.ASM ; KERMIT - (Celtic for "FREE") ; ; This is the CP/M-80 implementation of the Columbia University ; KERMIT file transfer protocol. ; ; Version 4.0 ; ; Copyright June 1981,1982,1983,1984 ; Columbia University ; ; Originally written by Bill Catchings of the Columbia University Center for ; Computing Activities, 612 W. 115th St., New York, NY 10025. ; ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben, ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many ; others. ; ; Multi-file access subroutine. Allows processing of multiple files ; (i.e., *.ASM) from disk. This routine builds the proper name in the ; FCB each time it is called. This command would be used in such pro- ; grams such as modem transfer, tape save, etc. in which you want to ; process single or multiple files. ; Note that it will fail if more than 256 entries match the wildcard. ; ; revision history: ; edit 3: July 27, 1984 ; support LASM: remove exclamation points, link to CP4CMD. ; ; edit 2: June 7, 1984 (CJC) ; formatting and documentation; add module version string; redo movfcb, ; in preparation for moving DMA buffer (later...). ; ; edit 1: May, 1984 (CJC) ; extracted from CPMBASE.M80 version 3.9; modifications are described ; in the accompanying .UPD file. ; wldver: db 'CP4WLD.ASM (3) 27-Jul-84$' ; The FCB will be set up with the next name, ready to do normal ; processing (OPEN, READ, etc.) when routine is called. ; ; Carry is set if no more names can be found ; ; MFFLG1 is count/switch [0 for first time thru, pos for all others] ; MFFLG2 is counted down for each successive GETNEXT file call ; ; Technique used is to repeat SFIRST/SNEXT sequence N+1 times for each ; successive call, till sequence fails. CP/M does NOT allow disk-handling ; between SFIRST and SNEXT. ; called by: send, seof, dir mfname: ora a ; clear carry push b ;Save registers push d push h mvi c,setdma ;Init DMA addr, FCB lxi d,80H call bdos xra a ;A = 0 sta fcbext ;clear extension lda mfflg1 ;find out if "second" call in row ora a jnz mfn01 ;Were here before sta mfflg2 lxi h,fcb lxi d,mfreq lxi b,12 call mover ;.from FCB to MFREQ mvi c,SFIRST ;Search first lxi d,fcb call bdos jmp mfn02 ;and check results mfn01: dcr a sta mfflg2 ;store down-counter lxi h,mfreq ;SFIRST REQ name lxi d,fcb lxi b,12 call mover ;.from MFREQ to FCB mvi c,sfirst ;Search first old one,we got it before lxi d,fcb call bdos ;no error's expected -we got that before mfn01a: mvi c,snext ;Search next call bdos mfn02: push psw lda mfflg2 ;get "repeat file counter" ora a jz mfn02a ;if zero, check if SNEXT had ERROR dcr a ;count down sta mfflg2 ;store back pop psw ;no error-check, we got it before jmp mfn01a ;next SNEXT mfn02a: pop psw ora a jm mffix2 ;No (more) found call movfcb ;move data to fcb lda mfreq ;the original disk-designator sta fcb ;back into fcb lda mfflg1 ;get file-flag inr a ;increment sta mfflg1 ;and store for next go-around mvi a,0 ;Setup FCB sta fcbext ;clean up FCB for OPEN etc sta fcbrno mffix1: pop h ;restore registers pop d pop b ret ;and return mffix2: stc ;set carry jmp mffix1 ;return with CARRY set ; copy directory entry to FCB ; called with A/ entry number in directory (0-3) ; directory block in DMA buffer (buff) movfcb: add a add a add a add a add a ;* 32 mov c,a ; copy offset to bc mvi b,0 ; (high byte is zero) lxi h,buff ; get start of disk buffer dad b ; calculate start of directory entry lxi d,fcb lxi b,12 call mover ret ; Data storage for MFNAME (multi-file access) mfreq: DS 12 ;Requested name mfflg1: DB 0 ;First time thru flag for MFNAME mfflg2: DB 0 ;Down counter for MFNAME ; IF lasm LINK CP4CMD ENDIF;lasm  jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a 9-Aug-84 18:59:08-EDT,8761;000000000001 Return-Path: Received: from ACC.ARPA by COLUMBIA-20.ARPA with TCP; Thu 9 Aug 84 18:58:34-EDT Date: 9 Aug 1984 15:59 PDT From: Charles Carvalho Subject: Kermit-80: CP4ASM.DOC To: CC.DAPHNE@COLUMBIA-20 Reply-To: CHARLES@ACC Creating a runnable Kermit from the distribution kit: You will need two of the .HEX files from the distribution kit: CP402.HEX (the system-independent module) and one of the system-dependent overlay modules. The name of the system-dependent overlay is the first six characters of the switch used to generate it; see table 1 below. For systems which require an external terminal as console, the distribution kit overlays use the generic "crt" selection; after getting Kermit running, you may wish to reconfigure it to make use of your specific terminal. For purposes of illustration, we will assume the system-dependent overlay is called "foo.hex". The two hex files may be combined in two ways: if you do  not have MLOAD (a public-domain enhanced version of LOAD), you will have to use DDT, as follows: A>ddt cp4ker.hex NEXT PC 3500 0100 -ifoo.hex -r NEXT PC xxxx 0000 -^C A>save dd kermit40.com The page count ("dd") used in the SAVE command is calculated from the last address ("xxxx") given by DDT in response to the R command: divide this number by 100 hex, rounding up, then convert to decimal: 384F becomes 39 hex, which is 57 decimal; but 3700 becomes 37 hex, or 55 decimal. Be careful not to overwrite your running Kermit, if any, with this new version until you've tested it. If you do have MLOAD, the process is simpler: A>mload ker402=cp4ker,foo This produces ker402.com, which may be run directly. Test your new Kermit by running it. If it gives you a prompt, it might be OK. (don't delete your old one yet...). Instead of a prompt, you could get one of two messages indicating that the configuration information is invalid: ?Kermit has not been configured for a target system or ?Consistency check on configuration failed Of course, neither of these messages should appear if you're building Kermit from the distribution kit. The first message indicates that the overlay was not found where the system-independent module expected to find it, probably because the overlay address is incorrect; the second indicates that the version of CP4LNK used in the system-dependent module is incompatible with the system- independent module. Table 1 Systems supported by Kermit-80 Symbol System ap6551 Apple II with Z80 Softcard and 6551 ACIA in serial interface apmmdm Apple II with Z80 Softcard and Micromodem II in slot 2 bbII BigBoard II (terminal required) brain Intertec SuperBrain. cpm3 "generic": CP/M 3.0 (CP/M Plus) systems (terminal required) dmII DECMATE II gener "generic": CPM 2.2 systems supporting IOBYTE (terminal required) heath Heath/Zenith H89. kpII Kaypro-II (and 4; probably supports all Kaypro systems) mdI Morrow Decision I (terminal required) mikko MikroMikko mmdI Morrow Micro Decision I (terminal required) osbrn1 Osborne 1 osi Ohio Scientific robin DEC VT180 telcon TELCON Zorba portable trs80lb TRS-80 model II with Lifeboat 2.25C CP/M Display trs80pt TRS-80 model II with Pickles + Trout CP/M Display vector Vector Graphics. z100 Z-100 under CP/M-85 Table 2 Terminals known to Kermit-80 Symbol Terminal description crt Basic CRT, no cursor positioning adm3a Adm3a Display or lookalike tvi925 TVI925, Freedom 100 vt52 VT52 or VT52 emulator such as Heath H19, H29, etc. vt100 VT100 or emulator (most ANSI terminals should work?) Assembling Kermit-80 from the sources: Kermit-80 is built in two pieces from the following 12 files: The system-independent files: CP4KER.ASM - header file CP4DEF.ASM - definitions for both KERMIT and KERSYS CP4MIT.ASM - initialization, main loop, miscellaneous commands (BYE, EXIT, LOG, SET, SHOW, and STATUS) CP4PKT.ASM - the KERMIT protocol handler (SEND, RECEIVE, LOGOUT, and FINISH commands) CP4TT.ASM - the transparent commands (TRANSMIT, CONNECT) CP4CPM.ASM - CP/M commands (DIR, ERA) CP4WLD.ASM - the wildcard handler CP4CMD.ASM - the command parser CP4UTL.ASM - utility routines and data CP4LNK.ASM - linkage area description The system-dependent files: CP4TYP.ASM - system selection CP4SYS.ASM - system-specific code The system-independent module contains all of the system-independent files except for CP4LNK.ASM, which is assembled into the system-dependent module to provide the structures needed to connect the two modules. As distributed, the system-independent module is named CP4nn.HEX, where 4nn is the version number. The system-dependent module consists of CP4TYP.ASM, CP4DEF.ASM, CP4LNK.ASM, and CP4SYS.ASM. One copy of the system-dependent module is supplied for each supported system; the filename is the same as the switch which is defined to select that system (truncated to six characters). After assembling the two pieces separately, they are combined with DDT or MLOAD into a system-specific Kermit. If you want to rebuild the system-independent module, the only change you may need to make is to select the assembler to be used, in CP4KER.ASM. Define one of MAC80, M80, or LASM to TRUE to select it as the assembler; the others should be defined FALSE. Assuming you have the Microsoft Macro Assembler package (M80/L80), you'll need to do the following: A>m80 cp4ker=cp4ker.asm A>l80 /p:100,cp4ker,cp4ker/n/e This will produce CP4KER.COM. If you are using LASM instead, do this: A>lasm cp4ker LASM will generate CP4KER.HEX. If you're using MAC80, I can't help you. (Frank??) If you want to generate a system-dependent overlay for a particular system, you'll need to check three areas in CP4TYP.ASM: First, the overlay start address. The symbol "ovladr" is EQUated to the address of "lnkflg" in the system-independent module, as the starting address of the overlay (3400H for version 4.02). You'll need this if you're building the overlay with M80/L80. (you won't normally need to change this value) Second, the assembler being used. Again, define one of MAC80, M80, and LASM to be TRUE to select it, and define the others to be FALSE. The two modules (system-independent and system-dependent) do not need to be built with the same assembler. Third, the system configuration. Locate your system in table 1, then define the appropriate symbol TRUE, and the rest FALSE. If the system comes with a builtin console terminal, define all the terminal switches FALSE. If the system uses an external terminal as the console, locate the terminal in table 2 and define the appropriate symbol TRUE, and the remainder FALSE. If the terminal is not listed in table 2, use the CRT switch; in this case, VT52 emulation is not supported. In addition, there are a few general and system-specific symbols which may be altered to fit your system: apslot For Apple with 6551 ACIA, defines the slot number of the serial card  cpuspd Processor speed in units of 100KHz (currently used only for bbII and kpII for timing loops) tac For users connecting through ARPAnet TACs: set to TRUE if you wish the default TACTRAP status to be ON. (This may be overridden with the SET TACTRAP command) tacval For ARPANET TAC users: defines the default TAC intercept character (may be overridden with the SET TACTRAP command) If you are just assembling an existing configuration, you'll need to edit CP4TYP.ASM only. If you are adding support for a new system, you should not modify CP4DEF.ASM or CP4LNK.ASM; if you do, you'll have to change the system- independent module also. Eventually, CP4SYS.ASM will be split into separate files, each of which will generate one or more related systems. When this happens, you'll want to pick the one closest to your system to use as a starting point. After editing CP4TYP.ASM as necessary, assemble and link the overlay as follows: With M80 (where "xxxx" is the hex value of ovladr from CP4LNK.ASM): A>m80 cp4typ=cp4typ.asm A>l80 /p:xxxx,cp4typ,cp4typ/n/x/e With LASM: A>lasm cp4typ The overlay may then be merged with the system-independent module as described above (Creating a runnable Kermit from the distribution kit). Adding support for your system to Kermit: To be supplied. Basically, you'll only need to add a switch it CP4TYP.ASM to select your system, and add the system-dependent code to CP4SYS.ASM (I hope I've put enough hooks to allow this to be done easily). Adding new features to Kermit: To be supplied. Hang on, I've got this list of requests...  ; Data storage for MFNAME (multi-file access) mfreq: DS 12 ;Requested name mfflg1: DB 0 ;First time thru flag for MFNAME mfflg2: DB 0 ;Down counter for MFNAME ; IF lasm LINK CP4CMD ENDIF;lasm  jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a CP4MIT.UPD Changes between v3.8 and v4.02 of Kermit-80 4-Aug-84 The starting point was CPMBASE.M80/CPMBASE.UPD for version 3.9 of Kermit, FTP'd from Columbia University. CPMBASE.UPD has not been modified; it is now only of historical interest. CPMBASE.M80 was divided two separately assembled modules (hereinafter referred to as CP4KER and CP4TYP, after the first file in each). The sources consist of 12 files (one of which is assembled into both modules): CP4KER.ASM - header for system-independent module. Defines assembler to be used, and links (LASM) or includes (MAC80, M80) the remaining files. CP4MIT.ASM - main loop and small commands CP4DEF.ASM - common symbol definitions (for CP4KER and CP4TYP) CP4CMD.ASM - command parser CP4CPM.ASM - DIR and ERA commands CP4PKT.ASM - SEND and RECEIVE commands CP4TT.ASM - TRANSMIT and CONNECT commands CP4WLD.ASM - wildcard support CP4UTL.ASM - support routines and data (pure, impure) CP4TYP.ASM - selects target system and assembler to be used. Links or includes the rest of these files: CP4LNK.ASM - linkage sections CP4DEF.ASM - common symbol definitions (for CP4KER and CP4TYP) CP4SYS.ASM - system-dependent code The divisions within the system-independent files is not as clear-cut as it could be; I'm working on that. I started assembling the code with M80, and switched to LASM, to provide a system that could be built with a minimum of additional software beyond that provided in the basic CP/M system. (ASM could not be used, because it has no provision for multiple input files). Version 4.02 assembles identically with M80 and LASM; I expect MAC80 will also be able to assemble it. All code (and data) is assembled for absolute addresses; CP4KER starts at 100H, and CP4TYP starts at the first free page following CP4KER. There are two linkage sections used to pass control and share data between the two modules: one at 103H, containing a block of JMP instructions to routines in CP4KER which may be needed by CP4TYP; the other is at the beginning of the system-dependent overlay, containing a block of JMP instructions and variables shared by CP4KER and CP4TYP. The formats of these areas are defined in CP4UTL and CP4LNK, although they really should be defined in only one place; the common subset of the assemblers used does not include a mechanism to do this. CP4KER.ASM contains the following: TRUE, FALSE - for selecting options M80, MAC80, LASM - select the assembler to be used, since they require different directives CP4KER - defined TRUE so CP4DEF can link to the correct module for LASM, a LINK directive to chain to CP4DEF.ASM for MAC80 and M80, INCLUDE directives to include the remainder of the files in the module. CP4DEF.ASM Definitions for ASCII characters Definitions for BDOS calls Definitions for constants used in command tables CP4MIT.ASM entry linkage section (routines needed by CP4TYP: kermit, and nout) start - system-independent initialization kermit - main command loop bye command exit command help command log command set command (and all its subcommands) show command status command CP4UTL.ASM utility routines: escpr - prints the escape character keycmd - parses a keyword; jumps to main loop if error. cfmcmd - confirms a command; jumps to main loop if error. nout - decimal output of number in HL. prtstr - call bdos to output a string. rskp - do "skip return" - return to PC on stack plus 3. r - do "nonskip return" - return to PC on stack. (This is needed because calls to routines with skip returns must be followed by a 3-byte instruction, such as a JMP). getfil - call bdos to open a file, and set up variables for reading it. inbuf - read a sector from the file opened by getfil. outbuf - output a sector. text (almost pure storage): Kermit's name and version; prompts; error messages; status messages; help text for parser (except SET BAUD and SET PORT); command tables for parser (except SET BAUD and SET PORT); impure storage: for parser; for just about everybody else (break this down!) linkage section (overlaid by CP4TYP): consistency check info (3 words); initialized to zero here so we can detect absence of CP4TYP. jump tables for routines in CP4TYP data shared between CP4KER and CP4TYP: pointer to VT52 emulation strings pointer to command table for SET BAUD pointer to help table for SET BAUD pointer to command table for SET PORT pointer to help table for SET PORT various parameters whose defaults are system-dependent (including protocol parameters) other variables shared between CP4KER and CP4TYP: bmax, bmask, bshiftf, nnams Routine-by-routine changes: For each file, the order here more or less follows the order of routines in the sources. The primary exceptions are the system-dependent routines, which are described with the routines that call them. Other possible exceptions are routines that were moved, which may still be described where they used to be, due to oversight. CP4CMD.ASM: cmblnk: deleted; clrtop is now called directly. cmnb12: To erase current line, call clrlin instead of printing clrlin. Use prtstr instead of setting c=prstr and calling bdos. cminb2: To adjust for the delete key, call delchr instead of printing delstr. Move Kaypro dependency to CP4TYP. cmnb32: To erase character, call clrspc instead of printing clrspc. CP4CPM.ASM Move definition of NPL into this module. Call sysspc to calculate free space; algorithm is different for CPM3. sysspc: Use CPM3 algorithm (supplied by Bruce Tanner) for CPM3 systems, the old algorithm for all the others (CPM2 systems). CP4DEF.ASM: Move SOH to ASCII character section. Move BDOS next to BDOS calls. Separate CPM2-only and CPM3-only calls; add getfs for CPM3 Delete DIASW, nobody uses it. CP4MIT.ASM: general changes (formatting only) blank line added after unconditional transfers of control; indent some error (non-skip) returns; space or tab added between some labels and instructions. entry linkage table (new): ASEG/ORG moved to immediately before table, so nothing gets in between. jump to start, around entry linkage table, added. start: nop's were deleted, as they're not necessary? (unless DDT does something weird with the stack pointer, it's OK to leave it set at 0100H, because PUSH decrements before storing the data) print Kermit's version (Kermit-80 v4.00) (we do this as soon as possible, for identification if it quietly dies later) do consistency checks to see if we have a good configuration loaded. if so, call sysinit to do the system-dependent stuff. remove reenter label; proper re-entry point is now kermit: jump to kermit, instead of call; it never returns. sysinit: the system-dependent code was generalized where possible; this resulted in some changes to baud rate handling. Also, this made printing the version a bit easier. As with start:, we print the version as soon as possible to identify the victim. print "configured for " (after Kermit's version). if a specific terminal is being supported, print "with ". for iobyte systems, get bios addresses so we can bypass bdos for I/O to console and modem. get current iobyte and save as console iobyte. for osbrn1, move I/O routines above 4000H, read current baud rate, and set comm-line parity. for kpII and bbII, output command string to SIO chip to initialize comm-line. (correct documentation of SIO chip commands) for mikko, copy command string to (memory-mapped) SIO chip to initialize comm-line; set data mask to 0ffH (all 8 bits). for brain, get current comm-line speed. kermit: reload the stack pointer, as some error handlers jump back to kermit without cleaning up the stack. This is now the reentry point used when control-C is typed during file transfer. Also re-select the console, for iobyt systems. bye: call sysbye to do system-dependent connection termination. sysbye: for apple, drop carrier on modem. exit: call sysexit to do system-dependent program termination sysexit: for mikko, restore comm-line parameters altered in sysinit. setcom: added SET DEBUG ON/OFF command (note: no corresponding display in SHOW command (yet)) Added SET TACTRAP ON/OFF/CHARACTER for TAC support (from Toad Hall). Added subroutines onoff and chkkey to simplify SET subcommands. vt52em: if vtflg contains 0FFH, say "(not implemented)" and jump back to command loop. otherwise, accept an "ON" or "OFF" and set vtflg accordingly. setdbg: Since the debugging code could no longer be conditionally assembled, the SET DEBUG ON/OFF command was added. The debugging code is always present, and tests dbgflg to see if any debugging output should be produced. dbgflg is initialized to 0 (OFF) in CP4LNK.ASM. baud: If spdtab is non-zero, it points to a command table of speed keywords to be used to process the speed command, and spdhlp points to the corresponding help text. All bits of the value obtained from the speed table is stored in 'speed' for the STATUS command, and sysspd is called with the 16-bit value in DE. If spdtab contains zero, "(not implemented)" is printed. sysspd: The speed selection menus for brain and osbrn1 have been replaced with a keyword table. Brain now uses the same table as kpII, allowing the selection of 19200 baud; I'm not sure this speed will work, but decided to try it anyway. Osbrn1 uses a two-entry command table, allowing 300 and 1200 baud; the values returned are OSBR03 and OSBR12, simplifying the sysspd routine. for the brain, get the saved baud rates (stored by the bios?) and replace the left nibble with the low 4 bits of DE. Save the new value (for the bios?) and output it to the baud rate generator port. for the osbrn1, reset the ACIA, delay a while, and output the low byte of the speed to the ACIA. for the bbII, load the specified time constant into the appropriate channel of the CTC chip. for the kpII, output the speed to the channel A baud rate generator port. for the mikko, write the 16-bit baud rate multiplier into both the receive clock and transmit clock generators. prtset: SET PORT is handled in the same manner as SET BAUD: if prttab contains zero, "(not implemented)" is printed; otherwise, prttab contains a pointer to the command table, and prthlp contains a pointer to the help text. After getting the keyword from the user, sysprt is called with the keyword's value. sysprt: The processing here is essentially unchanged from version 3.9: the value is the address of a 3-byte entry which gives the iobyte value, the BDOS function, and (for robin) the hardware port address. status: trivial change to command confirmation; it now looks just like the SHOW command. stat01: this is the actual status display, called by the SHOW and STATUS commands, and by the S command in terminal mode. Each parameter is now displayed by a separate routine, so we can eventually support a "SHOW " command. if vtflg, the VT52 emulation flag, contains 0FFH (not implemented), don't say anything about VT52 emulation; otherwise, report VT52-Emulation ON or OFF. if spdtab is non-zero, baud rate setting is supported, so report baud rate: if speed is 0FFFFH, report "speed is indeterminate", else look up speed in spdtab. If found, print speed, else report "speed is indeterminate". This should now work for all systems with SET BAUD capability. CP4PKT.ASM general: Calls with prtstr with DE containing one of scrend, screrr, scrfln, scrnp, scrnrt, scrst, rppos, and sppos were replaced with calls to these routines, which will typically position the cursor to the desired place and clear the remainder of the line. init: Instead of printing outlin and outln2, sysscr is called with DE containing the address of Kermit's name and version. Move initialization done by init1 to receive command; send command doesn't need it (getfil does all necessary file initialization) sysscr: print banner (outlin) for systems with cursor positioning support, print Kermit's version (from DE) print system name (sysver) print field names (outln2) (the system name is enclosed in square brackets; the open bracket is printed here, and the close bracket is in outln2) if dbgflg is set, print debug field names (outln3) spack: Delete debug code that terminated packet with a $, as a routine (dmptxt:) was added to output the whole packet (null-terminated). outpkt: Replace the sequence: IF iobyt lda prtiob ;Set up for output to go to the comm port sta iobyte ;Switch byte directly ENDIF;iobyt with: call selmdm ; Set up for output to comm port if iobyt Likewise, replace IF iobyt lda coniob ;Set up for output to go to the console port sta iobyte ;Switch directly ENDIF;iobyt with: call selcon ; set up for output to console port Selmdm and selcon are in CP4SYS.ASM; they contain the loads and stores from above, conditionally assembled under IOBYT, followed by a ret. At outpk6:, replace conditionally assembled debug code with test of dbgflg. Also call dmptxt instead of prtstr, so we print the whole packet. TACtrap support added: if tacflg is non-zero, it's the TAC intercept character, and must be doubled when seen in an outbound packet. Replace calls to outchr with calls to outmdm or outcon, depending on whether we want to talk to comm line or console. Outmdm and outcon are in CP4SYS.ASM. Note that parity must be set before calling outmdm; outchr used to do it, but outmdm does not. inpkt: At inpkt6:, replace conditionally assembled debug code with test of dbgflg. Also call dmptxt instead of prtstr, so we print the whole packet. inchr: Fuzzy timer support has been generalized. The initial value should be system-dependent, based on system speed and the time required to get an input character from the modem. If we get a control-C, jump to kermit instead of reenter. error: changing screrr to a subroutine from a string made error9 unnecessary. dmptxt: this routine is prints the null-terminated string pointed to by HL. CP4SYS.ASM: Integrated ap6551 (ACIA) support from Jon Beeson and Francis Wilson and numerous fixes from Bruce Tanner. Add delimiters around text in .printx's so M80 is happy too. (Currently, the M80/MAC80 assembly flags are used only to decide whether or not we should do the .printx's; if either is true, the .printx's are included). Add definitions for bbII. Although the bbII supports a builtin console, I've left that out for now; it looks like a superset of the ADM3A. Modify selection of defesc: for systems or terminals where ']' is a shifted character, use '\' instead (some of these are just guesses...). Define vtval: initial value of VT52 emulation flag. If generic CRT, can't do VT52 emulation; if terminal uses VT100 sequences (i.e. Robin, dmII), default to VT52 emulation off (but we can do it); for others, default VT52 emulation on. Things like defesc and vtval probably belong in CP4TYP.ASM, so the user can override them without modifying CP4SYS.ASM. outchr: replaced by outmdm (but parity must be set first): inpchr: replaced by inpmdm: prtout: replaced by outmdm: baudtb: replaced by command table (brain, osbrn1) sysexit, syscon, syscls, sysinh, sysint, sysflt, sysbye, sysspd, sysprt, sysscr, sysspc: described elsewhere (where they are called) selmdm, selcon: For iobyt systems, these routines update IOBYTE appropriately. For the Morrow Decision I, they cause the correct port to be selected. For the other systems, they do nothing. inpcon: gets a byte from the console, via dconio bdos call for non-iobyte systems, or by calling the bios for iobyte systems. Zero is returned if no character is available. outcon: outputs a byte to the console. For the Kaypro, it uses the bdos conout function for tabs, and dconio for all other characters. I haven't looked into this yet, but suspect that calling dconio will result in not knowing the current column, which in turn will cause the wrong number of spaces to be generated for tabs. For iobyte systems, we call the bios; for the rest, except the Kaypro, we use the dconio bdos function. outmdm: outputs a byte to the modem. This routine preserves bc and hl, although outcon doesn't. This will be reconciled eventually; I think we ought to make outmdm and outcon the same for iobyte systems. inpmdm: gets a byte from the modem. Returns zero if nothing there yet. Again, this ought to be the same as inpcon for iobyte systems. outlpt: outputs a byte to the printer. csrpos: given desired row in B and column in C, moves the cursor. Home position is (1,1). Since this routine is referenced by the linkage section, a dummy routine is provided for the OSI and CRT systems, although it should never be called. scrnp: For systems with cursor positioning, call csrpos with the desired screen position. For OSI and CRT systems, just print a space. scrnrt: For systems with cursor positioning, call csrpos with the desired screen position. For OSI and CRT systems, just print " %". scrfln, screrr, scrst, scrend: For systems with cursor positioning, these routines call csrpos with the desired screen position. For OSI and CRT systems, print a crlf. rppos, sppos: For systems with cursor positioning, these routines call csrpos with the desired screen position. For OSI and CRT systems, print a header ("RPack:" or "SPack:"). clreos: For systems with cursor positioning, print the erase-to-end-of-screen string from the VT52 emulation table. clreol: For systems with cursor positioning, print the erase-to-end-of-line string from the VT52 emulation table. delchr: If echoing 'del' to the screen does nothing, just print a backspace. Otherwise, print delstr to clean the mess off the screen. clrspc: output space,backspace to erase the character at the current cursor position. clrlin: print eralin to erase the current line. clrtop: print erascr to clear the screen and move to the home position. prtstr: Duplicate for CP4TYP. We could put prtstr in the linkage section, but I was trying to restrict that to JMP instructions, to avoid having to calculate where everything is. rskp: Another duplicate. Terminal tables: general: define screen format (outln2, outln3) replace outlin + versio with sysver, outlin. clrlin becomes eralin. clrtop becomes erascr. for escape sequences with no translation, print nothing. brain: add curldn. remove rppos, sppos. heath/z100/telcon: make vt52-compatible: clear screen is $H$J, not $E$H; erase to EOL is $K, not $l. trs80lb: graphics mode? adm3a, tvi925, vt52, vt100: add ttytyp (terminal name string) for initialization kpii: The Kaypro echoes DEL as a printing character; it uses delstr (backspace, space, backspace, backspace) to erase it. for ti: (reverse linefeed) use insert line rather that cursor up, in the hope that it will only be used on the top line. (True for VMS EDT and Unix vi) CP4TT.ASM xmit: getfil no longer has a skip return: remove following "jmp kermit". xnext: Add calls to selmdm to select proper output port. This allows us to use the same output routine for terminal mode and file transfer mode. Use inbuf to get next buffer, instead of xbuf. xbuf: deleted; xmit calls inbuf instead. telnet: Drop what appears to be an extra call to ckdial (apple only); ckdial is called again as part of the system-dependent code for starting the session. Replace code for robin, apple, osbrn1 with call to syscon. syscon: For robin, print an extra message about control-S For apple, do dial support. For the osborne, patch BIOS so back-arrow generates DELETE code. prtchr: made system-independent. To get character, it calls selmdm and inpmdm. system-specific code changed to generic: NUL, DEL, XON, and XOFF are not sent to the terminal. (We should alter this to support HANDSHAKE and TURNAROUND options.) added call to sysflt - system-dependent filter to take care of any other characters we don't want to send to the terminal. If vtflg is positive, VT52 emulation is enabled. (negative means VT52 emulation is not supported for this system; zero means supported but currently disabled) vt52: generalized. we accumulate a whole cursor positioning sequence, and evaluate the row and column, then call csrpos to do it for the console. If the escape sequence is not recognized, we swallow the escape and the following character, just like a real VT52, so as not to screw up the console. We now respond to 'Z' (query terminal type), claiming to be a VT52 without a local printer (I vaguely recall some commands to control the optional printer, as well as a different response saying we've got one, but I'll leave that to someone who needs to emulate a VT52 with printer). Still not supported (besides printer): '>' and '=' (alternate keypad support); '[' and '\' (hold-screen support). logit: Use setpar, outmdm instead of prtout. Note that we still assume host does XON/XOFF support, and can react to XOFF within a few character times (unreasonably fast). prtout: deleted. use outmdm instead (call selmdm and setpar as appropriate). other system dependencies are taken care of by sysflt. conchr: Made system-independent - calls I/O routines i n CP4TYP. intchr: When C is seen, call syscls to do system-dependent stuff for return to local system. While printing help text, call sysinh to print extra system-dependent help. For 0, send null with proper parity. syscls: For Osborne, re-patch BIOS so backarrow generates backspace. sysint: For apple, 'D' is Disconnect Modem command. For robin, dmII, bbII, and kpII, 'B' is Send Break command CP4TYP.ASM Remove DEBUG conditional. Add MAC80, M80, and LASM, for those assemblers. Add OVLADR, address at which overlay is linked. This is set from the value of LNKFLG in CP4KER. Set TRS80 equal to TRS80LB OR TRS80PT, so it doesn't need to be set by the user. Add BBII, for Ferguson Big Board II. If using the built-in terminal of the bbII, define ADM3A EQU TRUE. Add VT52 and VT100 as supported terminal types for systems without an integrated terminal. (I don't know how many micro owners have VT52's; I added it for my Heathkit H-19) CP4UTL.ASM: Utility routines: compp, countp, ackp, and tryagn were moved to CP4PKT.ASM. Text: The string "Kermit-80 Vx.y " was moved from the system version string (versio:) to version: in CP4UTL.ASM. I also extended the minor version to 2 digits so I can keep track of interim releases during testing. outln2 was moved to CP4SYS.ASM, as it is used only for systems with cursor positioning. erms20, erms21 added for consistency checks at initialization. infms8 no longer includes TRS-80 help text; that is printed by syscon in CP4SYS.ASM inms11 was moved to CP4SYS.ASM. sethlp was changed to include line for the SET DEBUG command; minimum abbreviations changed. (sethlp and tophlp don't follow the same conventions...). prthlp was moved to CP4SYS.ASM. inthlp was modified to remove system-dependent text; sysinh will describe the additional commands (including B for dmII). vtemst unconditionally generated. osbmsg removed; no longer needed. spdst, spdust unconditionally generated. COMND tables: SET DEBUG added to SET keyword table prttab, spdtab now contain address of SET PORT, SET SPEED command tables in CP4SYS.ASM. Impure data: ecoflg moved to linkage section. vtvflg, vctccc are no longer needed; replaced by vtyval. vtflg moved to linkage section. prtfun, prtiob, coniob, prtadr moved to CP4SYS flwflg, ibmflg, cpmflg, parity, escchr moved to linkage section. spsiz, rpsiz, stime, rtime, spad, rpad, spadch, rpadch, seol, reol, squote, rquote, chktyp moved to linkage section. curchk, inichk not initialized. speed moved to linkage section. bmax, bmask, bshiftf, nnams moved to linkage section, for sysspc. mfreq, mfflg1, mfflg2 moved to CP4WLD.ASM. osbaud replaced by speed. osbrn1 I/O routines (starting at osmove) moved to CP4SYS.ASM kpstbl, miotbl, mintbl moved to CP4SYS.ASM filflg removed; file handling code no longer needs it. linkage section: (new) this section starts at the next available page boundary (to lessen its chances of moving from version to version, allowing the same configuration overlay to be used). OVLADR in CP4TYP.ASM must be set to the address of lnkflg in CP4KER (from the listing). The linkage section contains: lnkflg: one word, initialized to zero by CP4UTL.ASM. CP4LNK.ASM overwrites this with what it believes is the length of this linkage section; CP4KER verifies this value at startup and refuses to run if the value is incorrect. lnkent: one word, again initialized to zero by CP4MIT.ASM. CP4LNK.ASM overwrites this with the expected length of the entry section starting at 0103H; CP4KER refuses to run if this value is incorrect. (unnamed) one word, which is not currently checked by CP4KER. This could be used to hold the overlay's version number. The jump table follows the three-word header. After the jump table, space is saved for variables used by both CP4KER and CP4TYP. CP4WLD.ASM: mfname: Changed a few occurences of 'push a/pop a' to 'push psw/pop psw'. erged with the system-independent module as described above (Creating a runnable Kermit from the distribution kit). Adding support for your system to Kermit: To be supplied. Basically, you'll only need to add a switch it CP4TYP.ASM to select your system, and add the system-dependent code to CP4SYS.ASM (I hope I've put enough hooks to allow this to be done easily). Adding new features to Kermit: To be supplied. Hang on, I've got this list of requests...  ; Data storage for MFNAME (multi-file access) mfreq: DS 12 ;Requested name mfflg1: DB 0 ;First time thru flag for MFNAME mfflg2: DB 0 ;Down counter for MFNAME ; IF lasm LINK CP4CMD ENDIF;lasm  jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a  POLICY ON COMMERCIAL USE AND DISTRIBUTION OF KERMIT Frank da Cruz Columbia University Center for Computing Activities June 1984 The KERMIT file transfer protocol has always been open, available, and free to all. The protocol was developed at the Columbia University Center for Computing Activities, as were the first several KERMIT programs. Columbia has shared these programs freely with the worldwide computing community since 1981, and as a result many individuals and institutions have contributed their own improvements or new implementations in the same spirit. In this manner, the number of different systems supporting KERMIT implementations has grown from three to about sixty in less than three years. If Columbia had elected to keep the protocol secret, to restrict access to source code, or to license the software, the protocol would never have spread to cover so many systems, nor would the programs be in use at so many sites, nor would the quality of many of the implemementations be so high. Although KERMIT is free and available to anyone who requests it, it is not in the "public domain". The protocol, the manuals, the Columbia implementations, and many of the contributed implementations bear copyright notices dated 1981 or later, and include a legend like Permission is granted to any individual or institution to copy or use this document and the programs described in it, except for explicitly commercial purposes. This copyright notice is to protect KERMIT, Columbia University, and the various contributors from having their work usurped by others and sold as a product. In addition, the covering letter which we include with a KERMIT tape states that KERMIT can be passed along to others; "we ask only that profit not be your goal, credit be given where it is due, and that new material be sent back to us so that we can maintain a definitive and comprehensive set of KERMIT implementations". Within this framework, it is acceptable to charge a reproduction fee when supplying KERMIT to others. The reproduction fee may be designed to recover costs of media, packaging, printing, shipping, order processing, or any computer use required for reproduction. The fee should not reflect any program or documentation development effort, and it should be be independent of how many implementations of KERMIT appear on the medium or where they came from. It should not be viewed as a license fee. For instance, when Columbia ships a KERMIT tape, there is a $100.00 reproduction fee which includes a 2400' reel of magnetic tape, two printed manuals, various flyers, a box, and postage; there is an additional $100.00 order processing charge if an invoice must be sent. The tape includes all known versions of KERMIT, including sources and documentation. Commercial institutions may make unlimited internal use of KERMIT. However, a question raised with increasing frequency is whether a company may incorporate KERMIT into its products. A hardware vendor may wish to include KERMIT with its standard software. A software house may wish to incorporate KERMIT protocol into its communications package, or to distribute it along with some other product. A timesharing vendor or dialup database may wish to provide KERMIT for downloading. All these uses of KERMIT are permissible, with the following provisos: . A KERMIT program may not be sold as a product in and of itself. In addition to violating the prevailing spirit of sharing and cooperation, commercial sale of a product called "KERMIT" would violate the trade mark which is held on that name by Henson Associates, Inc., creators of The Muppet Show. . Existing KERMIT programs and documentation may be included with hardware or other software as part of a standard package, provided the price of the hardware or software product is not raised significantly beyond costs of reproduction of the KERMIT component.! . KERMIT protocol may be included in a multi-protocol communication package as one of the communication options, or as a communication feature of some other kind of software package, in order to enhance the attractiveness of the package. KERMIT protocol file transfer and management should not be the primary purpose of the package. The price of the package should not be raised significantly because KERMIT was included, and the vendor's literature should make a statement to this effect. . Credit for development of the KERMIT protocol should be given to the Columbia University Center for Computing Activities, and customers should be advised that KERMIT is available for many systems for only a nominal fee from Columbia and from various user group organizations, such as DECUS and SHARE. Columbia University holds the copyright on the KERMIT protocol, and may grant permission to any person or institution to develop a KERMIT program for any particular system. A commercial institution that intends to distribute KERMIT under the conditions listed above should be aware that other implementations of KERMIT for the same system may appear in the standard KERMIT distribution at any time. Columbia University encourages all developers of KERMIT software and documentation to contribute their work back to Columbia for further distribution. Finally, Columbia University does not warrant in any way the KERMIT software nor the accuracy of any related documentation, and neither the authors of any KERMIT programs or documentation nor Columbia University acknowledge any liability resulting from program or documentation errors. These are general guidelines, not a legal document to be searched for loopholes. To date, KERMIT has been freely shared by all who have taken the time to do work on it, and no formal legalities have proven necessary. The guidelines are designed to allow commercial enterprises to participate in the promulgation of KERMIT without seriously violating the KERMIT user community's trust that KERMIT will continue to spread and improve at no significant cost to themeselves. The guidelines are subject to change at any time, should more formal detail prove necessary. Commercial organizations wishing to provide KERMIT to their customers should write a letter stating their plans and their agreement to comply with the guidelines listed above. The letter should be addressed to: KERMIT Distribution Columbia University Center for Computing Activities 612 West 115th Street New York, NY 10025  ; Data storage for MFNAME (multi-file access) mfreq: DS 12 ;Requested name mfflg1: DB 0 ;First time thru flag for MFNAME mfflg2: DB 0 ;Down counter for MFNAME ; IF lasm LINK CP4CMD ENDIF;lasm  jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a"vÄ!CP4MIT.ASM (4) 3-Aug-84$!9"0141!"ͣ!<271*4|dm|m*4|m?4&ͣ!v#ͣ!#ͣ!14142n2o:71@2="2"͉-!e'i!!O ÑoB?`í_\"ͣ!v{!͹vT4{!B4*0{!e'ͣ!v>\{!!?16!"H1\2h2j2|\vX#ͣ!v7.!(i!!PO  üBQÃÉøÚÒ`.!*24v\>Ý:\§:71271 :71=_v.!*i!!O {!v{!v{!'ͣ!2v4v2z4v281v2y4v291v2{4v2|41>5>2~4x2z4291v/!+2}4vI/!+2~4v/!)+ʃʀ;'ͣ!24:424v:u4M2u4v*k4|M*m4i!{!"w4W4v*o4|M*q4i!{!Z4vr/!+i!22{!:2{!v{!v:A1t,ͣ!3:u4?Pnz͆͒*k4|',ͣ!:z4@,ͣ!:u4@M,ͣ!:}4,ʣ!,ʣ!,ã!,ͣ!:|4@,ͣ!:{4@,ͣ!:81@.-ͣ!:~49-ʣ!>-ʣ!C- ʣ!I- ʣ!M-ã!R-ͣ!:w4![-*k4V#F#"2#N##![-*2ã!-ͣ!!:4_#-ã!,ͣ!O!à!v-ͣ!:91@|-ͣ!,:4ʣ!_à!,£!,ã!$ͣ!vCP4PKT.ASM (3) 27-Jul-84$b1>ʤ226$ͯ-4b1ͣ!>12S122>Rçͯ2U1!"W1"Y12V12[134!̈́!>R2]104*W1̈́!:]1D^F͓R-:]1F&C$:U12U1$vA$($v:[1>m"ͣö<2[1>12S1ÿSˆ:[12\12[1:2:2!b1ͳ !b1r 22>Yö:T12S1>F2]1E¼~ö:[1"ͣö<2[1ÿS:\1m"ͣö<2\1:V1=?G:2¼2[1!b1r 22>YöZ :\1"ͣö F6¼ö:[12\1>D2]1:U1Zȯ2U1BS¼22>Yö>C2]1E¶~ö:[1o"ͣö<2[1ÿDʙ:\1"ͣö :[12\1:2K ö2[122O:U1O>22y2b1>YöF:\1"ͣö Z7¼:2:b1D(*H1:D1=6# !ö\2U1:[12\1>F2]1E¶~ö>\v{!_(#ͣvͯ2V12[12<1!"W1"Y134!̈́!>12S1>S2]104*W1̈́!:]1DŸq ÈFª͜ ÈZµh ÈS :]1Fˆ&ÈB ÈC$:U1$vA($v($v:[1 "ͣö<2[1>12S1:42T1!b1r 22:W122>Söí!Ys :2!b1ͳ :[12\12[1:T12S1>F2]1ͮ!N‘ :V1F2]1E¶~ö:[1 "ͣö<2[12U1!b1"L1!]"J1x >.*L1w#"L1 x *J1~#"J1! *L1w#"L1 y22*L1>$w-4b1ͣ!:V122>Föí!YO :[12\12[1 D 2R1>D2]1¶>Z2]1Nf :V11y :~4y :<1 y >2<1y*L1w#"L1:R1 :R122:V122>Döí!YF :2:[12\12[1:2$ :b1Z 2U1X$ 2U1:U11 >Z2]1 ; 2R1¶>Z2]1N] :V1D2b1>22>Zöí!Y :[12\12[1\:U1Z  ͮ!2U1>F2]1>B2]1N :V1Böí!YP :[12\12[1>C2]1Ng :V122> 24>#24>&2=1>12T1~ 24:2##~ 24:2#~@24:2#~ 24:2#~24:2#>2>1~N9 9 Y1 :~49 >2>19 2=1>2>1:2#~G:42T122!b1"F1:4G:>1e :=1O!25!!D15y !í!*F1~#"F1• :2=22~#"F1· ~#"F1!25W怳_zʷ ʷ z@*H1w#"H1e :4O:S11G:422!#2"N1:2= xè!22:D1= 2D1 ! x¨!*H1~#"H1W_::>1::2=22*N1:=1w#"N1zW ll:>1V:=1[z³!25*N1q#"N1zóœ:}4ʋʚ*H1:D1Wz2D1xè!~#ʆ>22!25*N1q#"N1:2@*N1w#"N1 *H1+"H1!D14xè!>!b1"L1!]"J122222\ p#< *L1~a_#."L1!e"J1:222> 22Ip"L1*J1w#"J1:2<2222*L1~#"L1p.5*L1~aT_p#"L1*J1w#"J1:2<22 I*L16$-4b1ͣ!:{4/\/0$ͣ:2¥:222P< ±=_!\6&!\ ~w# ¿\x{ò{ :2_òA#ͣ!2!]~#  x&>.!e>$2ͣ!\2h2j2|>2D1!"H1\¨!"ͣ{!2[1>12S1:[1}e#ͣ!v<2[122>22!b16F>GtlYvEl͉v{!͹vv2[1>12S1:[1#ͣ!<2[122>22!b16L>GYʨ!E͉22!^1>w#:S11G:2#w#O:2 w#O>G:2w#O>G:2I=22~#O>G3:S12zcy? w#Ñ6!_1KBz w#xGy w#y? w#:4w#w4:422:2=22:4!_ 4á:y44<4!_194!^1~!_ 4:4!_ 4#4è!í!͙͙í!2_1O:S11Gy#22͙í!222`1O>G:2 22͙í!222a1O>G:222!b1"L1:222͙í!*L1w#"L1O>Gg͙í! 22:S12ҽy?G:2*L16!_1KBzW:2¹͙í! 22xGyG:2¹͙í! Gy?¹*L16:2è!!1"P1ͦí!#Bͦí!B!1"P1*P1w#"P1G:41:|4s:]1Ssͦsh*P1+6:y4ʐ#494!194!1"P1è!*P1~#"P1¨!*s4":14 4G:~4xè!44 v@2U1:91ʮ*:1+":1|®~;_O!^ {O!> ~#V_#~W# !1BRcs ƍ#2$FW6etHZӾl~*4>A2]1ÏA"ͣ!:2O!b1 >$wb1ͣ!*44ͣ!!"]4>A2]1:V12222>Nö34*Y1#"Y1̈́!&ͣ64ͣ!'4:V1G:2Yö<2\1:V1=?G:2¼~_4#9CP4TT.ASM (3) 27-Jul-84$>\v{!ͮ!~(#ͣ!vN%ͣ!O!&&ͣ!O!R&ͣ!>2A12B1ͻ ʟ:61uO2X0e0*H1:D1G!*H1:D1G~#  :X0 2X0261"H1x2D1y2E1:E12Y0!e0"0ͻ:B1:Y0=]2Y04*0~#"0!_ 4:4I!_ 4:z4{_4422ͻ~:2 ʟä́n&×̈́v\2A1{!\$ͣ!O!$ͣ!O!$ͣ!E4ͻvï4 44ʻʻ _:u4:@1^û{>2@1ûQ4ʻ:?1&4:8144û2B1û*H1s#"H1}>!_ 4\M"ͣ!>!_ 4!"H1³{Yo>2@1ZʕALA*i4_4ͣ!2@1>!_ 4>/!_ 4>K!_ 4Ð{2C1>2@1ɯ2@1{O:C1G4`44ʨ!_22:v4 4{!_ 44:z4ʨ!{_4è!4 G_CK$ͣ!H4:?1ȯ2?1C$ͣ!*H16\\SVè!`Rk:A1k x?™:A1~+ͣ!+ͣ!K4<,ͣ!O!N,ͣ! x0°!_4 44è!:v4x!_4 44è!xN4è!4è!CP4CPM.ASM (3) 8-Jul-84$\>:\" 2\!] 6?#:\ :71@2%͠!$ͣ!>24e?ù Pù!]͑>.̈́͑!45t̝6͂>:̈́Â͂> _~̈́#‘͠!6͠!:71=_v2n2o:\=_c4%ͣ!:\<@2%%%%ͣ!̈́!,%ͣ!é#\:}o:~2~:}2}o:~g :4O /o LX X͂͂̈́!>k̈́##~24#~24##^#V"4>\v\<Ÿ(#ͣ!v\;%ͣ!vCP4WLD.ASM (3) 27-Jul-84$2h:n2o!\b f4\=2o!b\ f4\:o'=2oHL:b2\:n<2n>2h2}7DO! \ f4*M1CP4CMD.ASM (3) 8-Jul-84$"]0!9"[0"_0!e0"0"02X02Y0>2Z0͠! *[0!e0"0>2Z0*]0*[0!e0"0"02X02Y0>2Z0͠! *]02W0T i/ͣ!"a0]F2X0*0+"0"0!Y05?X $4x*a0è!!X06*a0w#"a0‘2X0*0+"0"0!Y05i?¼90ͣ!͠! *0>$w*0+"0e0ͣ!2X0õ $4è!"c0"a0F#"0*0"0x*0^#{?2X0!Y05*c0!͠! *0>$w*0+"0e0ͣ!õ2X0L*0+"0"0!Y05*0+~$h#w#:Y0<2Y0S:Y0<2Y0> w#"0"0ͣ! àÞ/ͣ!#^#V{è!a{_V#{"0*0"0K{F#*0~O*0 !F#~#a { _>20"06#"06 #< $2?Q!X06*0#"0*0#"0ñ%2X0*0+"0"0!Y05{22 r=*0 6?#.F# y22>$*0 *0+"0!Y05:2 ʵõ{ʽ è!.S{ʽ  *0 "0 -:p{½*0+~@"0+w-* :0{ʽÍ *0>?w#"0{-0{A_*0w#"0-:W0ʭ!/ 0<_ w#*0w#"0!Y04:X0T *0~#"0  ) :Z0>2Z0> Q 2Z0Q ?H H H *0+"0:X0 !Y04*0w#"0y  4 !e0"0!Y06õʚ ¾ !4:Y0== y 2Y04*0++"0õ?  ^ $4:Y0>2X0 *_0ͣ!CP4UTL.ASM (2) 3-Aug-84$!~4N!! .!8!+!=!G!L!L!L!L!L!L!L!:v4 b!$ͣ!:v4@_>r!D"ͣ!v> ڊ!|ć!}:_A" ###ɯ2D12612h2j2|\:61!!D16!"H1\!2D1>261è!\""ͣ!"H1>2D1è!Kermit-80 v4.02 $Kermit-80 x:>$ $ ?Unrecognized command$ ?Not confirmed$?Unable to receive initiate $?Unable to receive file name $?Unable to receive end of file $?Unable to receive data $?Disk full $?Unable to receive an acknowledgement from the host $ ?Unable to find file $?Unable to rename file$ ?Disk full$ ?Unable to tell host that the session is finished$ ?Unable to tell host to logout$ ?Kermit has not been configured for a target system$ ?Consistency check on configuration failed$Completed$Failed$%Renaming file to $ [Closing the log file]$ [Connected to remote host. Type $C to return; type $? for command list] $ [Connection closed, back at micro]$Control-$ (Not implemented) $Interrupted$  Directory for drive x: $ Drive $ has $K bytes free $ File(s) erased$ [Transmitting file to host: 1. Type any character to send a line. 2. Type RETURN to terminate the line and to get the next line (go back to 1.) (You may send other characters before RETURN.), or type $R to send the same line again, or type $C to abort transmission.] $ [Transmission done. Connected normally to remote host, type $Sending...$Receiving...$Warning: eighth bit cannot be sent$ For help, type ? at any point in a command$ Type the new escape character: $ Type the new TAC intercept character: $ BYE to host (LOGOUT) and exit to CP/M CONNECT to host on selected port ERA a CP/M file EXIT to CP/M FINISH running Kermit on the host HELP by giving this message DIR of current used Micro-disk LOG the terminal session to a file LOGOUT the host RECEIVE file from host SEND file to host SET a parameter SHOW the parameters STATUS of Kermit TRANSMIT file to host (in connect state)$ BAud (rate) BLock-check-type (for error detection) DEBug (messages ON / OFF) DEFault-disk (to receive data) Escape (character during CONNECT) File-mode (for outgoing files) Ibm (parity and turn around handling) Local-echo (half-duplex) PArity (for communication line) POrt (to communicate on) PRinter copy ( ON / OFF ) TAC Intercept Character TACtrap ( ON / OFf / Character) TImer ( ON / OFf ) Vt52-emulation Warning (for filename conflicts)$ PAD-CHAR PADDING$ 1-CHARACTER-CHECKSUM 2-CHARACTER-CHECKSUM 3-CHARACTER-CRC-CCITT$ ASCII BINARY DEFAULT$ ON to enable TAC trap OFF to disable TAC trap CHARACTER to enable TAC trap and specify intercept character$ EVEN MARK NONE ODD SPACE$ OFF ON$ R Send the same line again$ ? This message C Close the connection 0 (zero) Transmit a NULL S Status of the connection$ Typing another $ will send it to the host Command>$ Transmitting a file$ Local echo$ on$ off$ VT52 emulation$ File Mode$ default$ ASCII$ binary$ IBM flag$ File warning$ Printer copy$ "Escape char: $ Block check type: $-character$ Parity: $none$mark$space$odd$even$ Speed $is indeterminate (not SET)$Timer$ Current TACTrap Status/Intercept Character: $BYE$!!CONNECT$DIR$$$ERA$''EXIT$DINISH$GET$ HELP$LOG$ LOGOUT$RECEIVE$ SEND$SET$SHOW$STATUS$TRANSMIT$**BAUD$!!BLOCK-CHECK-TYPE$DEBUG$-- DEFAULT-DISK$$$ESCAPE$ FILE-MODE$IBM$ LOCAL-ECHO$PARITY$PORT$PRINTER$''TACTRAP$00TIMER$**VT52-EMULATION$WARNING$PAD-CHAR$PADDING$1-CHARACTER-CHECKSUM$112-CHARACTER-CHECKSUM$223-CHARACTER-CRC-CCITT$33EVEN$MARK$NONE$ODD$ SPACE$ OFF$ON$ASCII$BINARY$DEFAULT$ CHARACTER$OFF$ON$ ?Program error: Invalid COMND call$ ?Ambiguous$ ?Illegal CP/M file specification$ ?"*" not allowed in file specification$ Confirm with carriage return$1E07CC00C9FE46C2E7073A5C31FE05FAE307118B22CDA314C3B614CD2015C9FE5AC2F0 :1E07EA003708CDF914C2BC14CD02153AAD32FE01C205083A6231FE44CA28082A4831CF :1E0808003A44313DB7FA1608361A23C30B08CDFE21C3B6140E10115C00CD0500AF3217 :1E082&1325C31CD10153E46325D31C9FE45C2B614CD7E14C3B6143E02AF :1E084400115C00CDEB1BC37601CD7B21CDC91AD25F08112823CDA314C37601CDAF1420 :1E086200AF325631325B31323C31210000225731225931CD3334210000CD84213E3106 :1E0880003253313E5332 $31CD30342A5731CD84213A5D31FE44C29F08CD710AC388F8 :1E089E0008FE46C2AA08CD9C09C38808FE5AC2B508CD680BC38808FE53C2CE08CD088F :1E08BC00093A5D31FE46C2880811AF26CDED14C38808FE42C2D908CD070CC38808FE9C :1E08DA0043C2F108111D243A5531B7CAEB0811EE24CDED14C37601FE41C2FF08112810 :1E08F80024CDED14C37601112824CDED14C376013A5B31FE10FA190911F222CDA314B8 :1E091600C3B6143C325B313E313253313A8B34325431216231CD720C32AD323A573195 :1E09340032AC323E53CDFF10C3B614CDF611C3AD21FE59C27309CDF914C0C5"5,555595í5ã5Þ5ó5Ò5n5b5V5\5w5À5É5Ó4ï4ð4ñ4ò4ó4ø4ú4û4û4ü4>545T6 ^ ##1@25B315ͼ56ͼ55ͼ5:6ͼ5͹5_5{?6ͼ5ͼ5[56ͼ55ͼ5:y4#6ͼ5:\4=4_.!+~w 54^#VQ6ͼ5|_5}_5>5>5 >5|6ü5>5h5>5h5 >5h5 >5h5 >5x6ü55 55M6ü5H6ü55 ###~# x5 $configured for $ with $] Number of packets: Number of retries: File name:$ RPack: SPack:$VT52$HJ $HJ$ K$Y$A$B$C$D$E$F$G$H$I$J$K$Generic CP/M-80$$7Ø66 ###~# x¢6 $configured for $ with $] Number of packets: Number of retries: File name:$ RPack: SPack:$VT52$HJ $HJ$ K$Y$A$B$C$D$E$F$G$H$I$J$K$Generic CP/M-80$680CAC326 :1E0ABA000ACDE0143EFF323C3179E67F2A4C317723224C31043A5231B8F2940A3A5224 :1E0AD8003132AD323A563132AC323E44CDFF10C3B614CDF611C3AD21FE59C24 mfflg2: DB 0 ;Down counter for MFNAME ; IF lasm LINK CP4CMD ENDIF;lasm  jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a VOLUME 017 DESCRIPTION: KERMIT-80 V4.02 FOR GENERIC CP/M-80 WITH VT52 NUMBER SIZE NAME COMMENTS 017.1 2K -EBMMUG .017 DISK TITLE & CONTENTS OF VOLUME 017 (APR 4,'85) 017.2 8K COMMER .DOC COMMENTS RE:COMMERCIAL DISTRIBUTION 017.3 22K CP4CMD .ASM CP/M-80 IMPLEMENTATION FILE & COMMAND PARSER 017.4 8K CP4CPM .ASM CP/M COMMAND SUPPORT (DIR, ERA) 017.5 8K CP4DEF .ASM DEFINITIONS FOR BOTH KERMIT AND KERSYS 017.6 4K CP4KER .ASM HEADER FOR SYSTEM-INDEPENDENT MODULE 017.7 30K CP4KER .HEX THE HEX HEADER FILE 017.8 6K CP4LNK .ASM LINKAGE AREA DESCRIPTION 017.9 20K CP4MIT .ASM INITIALIZATION, MAIN LOOP & MISC. COMMANDS 017.10 28K CP4MIT .UPD CHANGES BETWEEN V3.8 & V4.0 OF KERMIT-80 017.11 62K CP4PKT .ASM THE KERMIT PROTOCOL HANDLER 017.12 62K CP4SYS .ASM SYSTEM-DEPENDENT CODES & TABLES 017.13 18K CP4TT .ASM TRANSPARENT COMMUNICATIONS HANDLERS 017.14 6K CP4TYP .ASM SELECTS TARGET SYSTEM & ASSEMBLER  017.15 22K CP4UTL .ASM VARIOUS UTILITIES AND DATA, AND END 017.16 4K CP4WLD .ASM WILDCARD HANDLER 017.17 10K CPMNEW .DOC HOW TO CREATE A RUNNABLE KERMIT 017.18 2K EBMDIR17.TXT THIS DISK DIRECTORY 017.19 2K K40FILES.LIS SIMILIAR TO THIS LISTING 017.20 14K KERMIT .COM THE KERMIT COMMAND FILE ) 017.5 8K CP4DEF .ASM DEFINITIONS FOR BOTH KERMIT AND KERSYS 017.6 4K CP4KER .ASM HEADER FOR SYSTEM-INDEPENDENT MODULE 017.7 30K CP4KER .HEX THE HEX HEADER FILE 017.8 6K CP4LNK .ASM LINKAGE AREA DESCRIPTION 017.9 20K CP4MIT .ASM INITIALIZATION, MAIN LOOP & MISC. COMMANDS 017.10 28K CP4MIT .UPD CHANGES BETWEEN V3.8 & V4.0 OF KERMIT-80 017.11 62K CP4PKT .ASM THE KERMIT PROTOCOL HANDLER 017.12 62K CP4SYS .ASM SYSTEM-DEPENDENT CODES & TABLES 017.13 18K CP4TT .ASM TRANSPARENT COMMUNICATIONS HANDLERS 017.14 6K CP4TYP .ASM SELECTS TARGET SYSTEM & ASSEMBLER # Files: 20 space used: 334k (52k free) -EBMMUG .017 0k : CP4KER .ASM 4k : CP4PKT .ASM 62k : CP4WLD .ASM 4k COMMER .DOC 8k : CP4KER .HEX 30k : CP4SYS .ASM 62k : CPMNEW .DOC 10k CP4CMD .ASM 22k : CP4LNK .ASM 6k : CP4TT .ASM 18k : EBMDIR17.TXT 0k CP4CPM .ASM 8k : CP4MIT .ASM 20k : CP4TYP .ASM 6k : K40FILES.LIS 2k CP4DEF .ASM 8k : CP4MIT .UPD 28k : CP4UTL .ASM 22k : KERMIT .COM 14k r JpQpWp4EDBACKUP$$$BAKNEW FILE:/25bp͒p͡pOqZ1:4:b2f5>0q:2i52g5:I!ڈp~<2k5>24!vi.>2vC!p ̀ʾp!p ̀p!8"J6×-!v.!6.292F2I2[[-*7"v"7p*7*7R|<2 72 7|D!"7>2 7%q)"7,q2 7!5wȷ!  .>2%!:C6!4̗!:~ͣwv:Jtqw::ʀq>26_7 !p ~87!p  :4=q!CS!7v!4:8:6q6 #:v+!4v8!5~8:4=r!SC AND DATA, AND END 017.16 4K CP4WLD.ASM WILDCARD HANDLER 017.17 10K CPMNEW.DOC HOW TO CREATE A RUNNABLE KERMIT 017.18 2K EBMDIR17.TXT THIS DISK DIRECTORY 017.19 2K K40FILES.LIS SIMILIAR TO THIS LISTING 017.20 14K KERMIT.COM THE KERMIT COMMAND FILE ERMIT AND KERSYS 017.6 4K CP4KER.ASM HEADER FOR SYSTEM-INDEPENDENT MODULE 017.7 30K CP4KER.HEX THE HEX HEADER FILE 017.8 6K CP4LNK.ASM LINKAGE AREA DESCRIPTION 017.9 20K CP4MIT.ASM INITIALIZATION, MAIN LOOP & MISC. COMMANDS 017.10 28K CP4MIT.UPD CHANGES BETWEEN V3.8 & V4.0 OF KERMIT-80 017.11 62K CP4PKT.ASM THE KERMIT PROTOCOL HANDLER 017.12 62K CP4SYS.ASM SYSTEM-DEPENDENT CODES & TABLES 017.13 18K CP4TT .ASM TRANSPARENT COMMUNICATIONS HANDLERS 017.14 6K CP4TYP.ASM SELECTS TARGET SYSTEM & ASSEMBLER 017.15 22K CP4UTL.ASM VARIOUS UTILITIES VOLUME 017 DESCRIPTION: KERMIT-80 V4.02 FOR GENERIC CP/M-80 WITH VT52 NUMBER SIZE NAME COMMENTS 017.1 2K -EBMMUG .017 DISK NAME & CONTENTS OF VOLUME 017 (APR 4,'85) 017.2 8K COMMER .DOC COMMENTS RE:COMMERCIAL DISTRIBUTION 017.3 22K CP4CMD .ASM CP/M-80 IMPLEMENTATION FILE & COMMAND PARSER 017.4 8K CP4CPM .ASM CP/M COMMAND SUPPORT (DIR, ERA) 017.5 8K CP4DEF .ASM DEFINITIONS FOR BOTH KERMIT AND KERSYS 017.6 4K CP4KER .ASM HEADER FOR SYSTEM-INDEPENDENT MODULE 017.7 30K CP4KER .HEX THE HEX HEADER FILE 017.8 6K CP4LNK .ASM LINKAGE AREA DESCRIPTION 017.9 20K CP4MIT .ASM INITIALIZATION, MAIN LOOP & MISC. COMMANDS 017.10 28K CP4MIT .UPD CHANGES BETWEEN V3.8 & V4.0 OF KERMIT-80 017.11 62K CP4PKT .ASM THE KERMIT PROTOCOL HANDLER 017.12 62K CP4SYS .ASM SYSTEM-DEPENDENT CODES & TABLES 017.13 18K CP4TT .ASM TRANSPARENT COMMUNICATIONS HANDLERS 017.14 6K CP4TYP .ASM SELECTS TARGET SYSTEM & ASSEMBLER 017.15 22K CP4UTL .ASM VARIOUS UTILITIES AND DATA, AND END 017.16 4K CP4WLD .ASM WILDCARD HANDLER 017.17 10K CPMNEW .DOC HOW TO CREATE A RUNNABLE KERMIT 017.18 2K EBMDIR17.TXT THIS DISK DIRECTORY 017.19 2K K40FILES.LIS SIMILIAR TO THIS LISTING 017.20 14K KERMIT .COM THE KERMIT COMMAND FILE  017.5 8K CP4DEF .ASM DEFINITIONS FOR BOTH KERMIT AND KERSYS 017.6 4K CP4KER .ASM HEADER FOR SYSTEM-INDEPENDENT MODULE 017.7 30K CP4KER .HEX THE HEX HEADER FILE 017.8 6K CP4LNK .ASM LINKAGE AREA DESCRIPTION 017.9 20K CP4MIT .ASM INITIALIZATION, MAIN LOOP & MISC. COMMANDS 017.10 28K CP4MIT .UPD CHANGES BETWEEN V3.8 & V4.0 OF KERMIT-80 017.11 62K CP4PKT .ASM THE KERMIT PROTOCOL HANDLER 017.12 62K CP4SYS .ASM SYSTEM-DEPENDENT CODES & TABLES 017.13 18K CP4TT .ASM TRANSPARENT COMMUNICATIONS HANDLERS 017.14 6K CP4TYP .ASM SELECTS TARGET SYSTEM & ASSEMBLER  VOLUME 016 DESCRIPTION: THE PUBLIC DOMAIN SOFTWARE DIRECTORY NUMBER SIZE NAME COMMENTS 016.1 2K -EBMMUG .016 DISK TITLE & CONTENTS OF EBMMUG.016 (APR 4,'85) 016.2 2K EBMDIR16.TXT THIS DISK DIRECTORY 016.3 274K PDOMAIN PUBLIC DOMAIN SOFTWARE IN CPMUG, SIG, PICONET & PASCAL Z LIBRARIES CPMUG VOLS 000-091 SIG VOLS 001-208 PICONET VOLS 001-034 PASCAL Z VOLS 001-018 !ڈp~<2k5>24!vi.>2vC!p ̀ʾp!p ̀p!8"J6×-!v.!6.292F2I2[[-*7"v"7p*7*7R|<2 72 7|D!"7>2 7%q)"7,q2 7!5wȷ!  .>2%!:C6!4̗!:~ͣwv:Jtqw::ʀq>26_7 !p ~87!p  :4=q!CS!7v!4:8:6q6 #:v+!4v8!5~8:4=r!SC#VOLUME 017 DESCRIPTION: KERMIT FILES NUMBER SIZE NAME COMMENTS CATALOG.017 CONTENTS OF EBMMUG VOL. 017 017.1 0K -EBMMUG.017 DISK NAME 017.2 8K COMMER.DOC COMMENTS RE:COMMERCIAL DISTRIBUTION 017.4 8K CP4CPM.ASM 017.5 8K CP4DEF.ASM 017.6 4K CP4KER.ASM 017.7 017.8 6K CP4LNK.ASM 017.9 017.10 017.11 017.12 017.13 017.14 6K CP4TYP.ASM 017.15 017.16 4K CP4WLD.ASM 017.17 10K CPMNEW.DOC 017.18 2K EBMDIR17.TXT 017.19 2K K40FILES.LIS 017.20 14K KERMIT.COM r JpQpWp4EDBACKUP$$$BAKNEW FILE:/25bp͒p͡pOqZ1:4:b2f5>0q:2i52g5:I!ڈp~<2k5>24!vi.>2vC!p ̀ʾp!p ̀p!8"J6×-!v.!6.292F2I2[[-*7"v"7p*7*7R|<2 72 7|D!"7>2 7%q)"7,q2 7!5wȷ!  .>2%!:C6!4̗!:~ͣwv:Jtqw::ʀq>26_7 !p ~87!p  :4=q!CS!7v!4:8:6q6 #:v+!4v8!5~8:4=r!SC$$%%&&''