├── .gitattributes ├── LICENSE ├── README.md ├── bin ├── mload.com ├── relhex.com ├── zmconfig.ovr ├── zminit.ovr ├── zmp-blnk.z80 ├── zmp-ovl.upd ├── zmp.cfg ├── zmp.doc ├── zmp.fon ├── zmp.for ├── zmp.hlp ├── zmp15+-.new ├── zmpx.com ├── zmterm.ovr └── zmxfer.ovr ├── hitechc ├── README.md ├── cpm.h ├── crtcpm.obj ├── ctype.h ├── libc.lib ├── memset.c ├── mktime.c ├── signal.h ├── string.h ├── time.h └── zcrtcpm.as └── src ├── cc.cmd ├── makeovl.cmd ├── ovbgn.as ├── ovloader.c ├── ovrcomp.cmd ├── ovrcomp.com ├── userdef.as ├── zccompil.cmd ├── zccompil.com ├── zicompil.cmd ├── zicompil.com ├── zmcompil.cmd ├── zmcompil.com ├── zmconf2.c ├── zmconf3.c ├── zmconf4.c ├── zmconfig.c ├── zmconfig.lnk ├── zminit.c ├── zminit.lnk ├── zmo-lb15.z80 ├── zmo-t412.z80 ├── zmo-t413.z80 ├── zmodmdef.h ├── zmp.c ├── zmp.h ├── zmp2.c ├── zmp3.c ├── zmterm.c ├── zmterm.lnk ├── zmterm2.c ├── zmterm3.c ├── zmterm4.c ├── zmxfer.c ├── zmxfer.lnk ├── zmxfer1.com ├── zmxfer2.com ├── zmxfer2a.c ├── zmxfer2b.c ├── zmxfer2c.c ├── zmxfer2d.c ├── zmxfer2e.c ├── zmxfer2f.c ├── zmxfer2g.c ├── zmxfer2h.c ├── zmxfer2i.c ├── zmxfer2j.c ├── zmxfer3.com ├── zmxfer3a.c ├── zmxfer3b.c ├── zmxfer3c.c ├── zmxfer3d.c ├── zmxfer3e.c ├── zmxfer3f.c ├── zmxfer3g.c ├── zmxfer3h.c ├── zmxfer3i.c ├── zmxfer4.com ├── zmxfer4a.c ├── zmxfer4b.c ├── zmxfer4c.c ├── zmxfer4d.c ├── zmxfer4e.c ├── zmxfer4f.c ├── zmxfer4g.c ├── zmxfer5.com ├── zmxfer5a.c ├── zmxfer5b.c ├── zmxfer5c.c ├── zmxfer5d.c ├── zmxfer5e.c ├── zmxfer5f.c ├── zmxfer5g.c ├── zmxfer5h.c ├── zmxfer5i.c ├── zmxfer5j.c ├── zmxfer5k.c ├── zmxfer5l.c ├── zmxfer5m.c ├── zmxfer5n.c ├── zmxfer5o.c ├── zmxfer5p.c ├── ztcompil.cmd ├── ztcompil.com ├── zxcompil.cmd ├── zxcompil.com ├── zzm.c └── zzm2.c /.gitattributes: -------------------------------------------------------------------------------- 1 | *.as linguist-language=Assembly 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZMP: A Zmodem terminal program for CP/M 2 | 3 | > ZMP is a communications/file transfer program for CP/M which performs 4 | > Xmodem, Xmodem-1k (often erroneously called Ymodem), true Ymodem and 5 | > Zmodem file transfer protocols. 6 | 7 | -- from the original ZMP.FOR file 8 | 9 | This is the 10 | [January 7th, 1989 source code for ZMP 1.5](http://www.classiccmp.org/cpmarchives/cpm/Software/WalnutCD/cpm/modems/zmodem/zmp-src.lbr). 11 | Note that this is not the same as the 1.5 version included in 12 | [ZMP15.LBR](http://www.classiccmp.org/cpmarchives/cpm/Software/WalnutCD/cpm/modems/zmodem/zmp15.lbr) 13 | and is missing several bits and pieces than were included in that release. 14 | 15 | This source has been *heavily* modified to compile and link with the 16 | [v3.09 release of the Hi Tech C](http://www.classiccmp.org/cpmarchives/cpm/Software/WalnutCD/cpm/hitech-c/) 17 | compiler. Though ZMP's author, Ron Murray, noted in the source code release 18 | that he'd used Hi Tech C, it was clearly a much earlier release. 19 | 20 | While I was pounding away at getting the source into a state that the 21 | compiler would accept (and fixing issues in the compiler's libraries - how 22 | did anyone actually get any work done with v3.09 back in the day?) I changed 23 | a few things that niggled at me: 24 | 25 | * Datestamps transferred in Y/Zmodem transfers. 26 | * Fixed long filename conversions on Y/Zmodem transfers. 27 | * Fixed issues displaying baud rate and send times when the baud rate 28 | is > 19.2K. 29 | * Removed superfluous CR sent to the remote end when a connection was 30 | established, which was a pita when connecting to a Linux box. 31 | * In keyboard macros, ! translates to a CR now, not CR/LF. 32 | * \ escapes ! and ~ so those literal characters can be used in 33 | keyboard macros. 34 | * Waits in keyboard macros now allow characters from the modem to 35 | be handled. 36 | * Keys in keyboard macros now have 25ms waits between them as to 37 | not overrun the remove system. 38 | * Long distance access code has been removed. 39 | * Quick dialing letters limited to A-T. 40 | 41 | ## Status 42 | 43 | It's pretty much done. I have gotten it to compile, link and run and 44 | I've been using it on my CP/M systems for years. From time to time I'll 45 | still find things to look at (and then there's the bugs that Ron Murray 46 | fixed between the version of the source code he released and the version 47 | that was used to produce the ZMP 1.5 binaries...). 48 | 49 | 50 | The Z3 aliases are now able to build the COM and OVR files. ZMCOMPIL.COM 51 | will build ZMPX.COM. OVRCOMP.COM will build all the OVR files. 52 | 53 | *Probably!* I was able to get everything to build on a 62K system, which 54 | has a far larger TPA than most Z-systems can manage (or at least what 55 | they could manage back in the day). 56 | 57 | Modified/new system files for Hi Tech C are included: cpm.h, time.h, 58 | libc.lib, memset.c, and mktime.c. 59 |  60 | -------------------------------------------------------------------------------- /bin/mload.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/bin/mload.com -------------------------------------------------------------------------------- /bin/relhex.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/bin/relhex.com -------------------------------------------------------------------------------- /bin/zmconfig.ovr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/bin/zmconfig.ovr -------------------------------------------------------------------------------- /bin/zminit.ovr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/bin/zminit.ovr -------------------------------------------------------------------------------- /bin/zmp-ovl.upd: -------------------------------------------------------------------------------- 1 | ZMP Overlay Update Information 2 | 3 | This file contains information on updating ZMP overlays designed for 4 | previous versions to the current version. Newer versions appear first in 5 | this file. 6 | 7 | Updates to ZMP14 Overlays for use with ZMP15. 8 | --------------------------------------------- 9 | 10 | The changes required here are associated with ZMP15's ability to access 11 | either of two UART ports, if available on the specific machine. One entry 12 | needs to be added to the jump table, and an extra routine needs to be added 13 | to set which port is in use. Lines which must be added to the overlay have 14 | an asterisk at the beginning. 15 | 16 | 1. Add an entry to the jump table. 17 | 18 | Add the following instruction at the end of the jump table, after the 19 | 'jp getvars' instruction and before the spare jumps: 20 | 21 | * jp setport ; Set the modem port being used 22 | 23 | 2. Add the setport routine. 24 | 25 | The following routine should be added into the code. A good place is 26 | immediately following the UART init code. 27 | 28 | *; 29 | *; Set the port. ZMP supplies either 0 or 1 as a parameter. You're on your 30 | *; own here -- your system is bound to be different from any other! You may 31 | *; implement a software switch on all the modem-dependent routines, or perhaps 32 | *; you can have one or two centralised routines for accessing the UARTs and 33 | *; modify the code from this routine to select one or the other. (Who said 34 | *; there was anything wrong with self-modifying code?). If you have only one 35 | *; UART port, or if you don't want to go through all the hassles, just have 36 | *; this routine returning with no changes made. Note that ZMP calls this 37 | *; routine twice -- once for each port value -- on initialisation. 38 | *; 39 | *setport: 40 | * ld hl,2 ; get port number 41 | * add hl,sp 42 | * ex de,hl 43 | * call getparm ; in HL (values are 0 and 1) 44 | * 45 | * ; <== Insert your own code here 46 | * 47 | * ; <== End of your own code 48 | * ret 49 | * 50 | *port: ds 1 51 | * 52 | 53 | End of changes ZMP14 --> ZMP15. 54 | 55 | -- Ron Murray 56 | 25/3/89 57 | 58 | =============================================================================== 59 | 60 | Updates to ZMP13 Overlays for use with ZMP14. 61 | --------------------------------------------- 62 | 63 | Some changes need to be made to accommodate the user-specification 64 | of drive/user area for the .OVR files. Changes need to be made in three 65 | places in your overlay (asterisks at the start of lines indicate which lines 66 | should be added): 67 | 68 | 1. Specify the required drive/user area. 69 | 70 | Add the following section after the mspeed equate: 71 | 72 | *;Set the following two equates to the drive and user area which will contain 73 | *; ZMP's .OVR files, .CFG file, .FON file and .HLP file. Set both to zero 74 | *; (null) to locate them on the drive from which ZMP was invoked. 75 | * 76 | *overdrive equ 'A' ; Drive to find overlay files on ('A'-'P') 77 | *overuser equ 0 ; User area to find files 78 | 79 | 2. Add to the jump table 80 | 81 | Add the following instruction at the end of the jump table, after the 82 | 'jp userout' instruction and before the spare jumps: 83 | 84 | * jp getvars ; get system variables 85 | 86 | 87 | 3. Add code at the end to get the system variables: 88 | 89 | Add the following code just in front of the overlay size test: 90 | 91 | *;Get address of user-defined variables 92 | * 93 | *getvars: 94 | * ld hl,uservars 95 | * ret 96 | * 97 | *uservars: 98 | * dw overdrive ; .OVR etc. drive/user 99 | * dw overuser 100 | * 101 | 102 | End of ZMP14 overlay modifications. 103 | 104 | -- Ron Murray, 20/11/88 105 | 106 | =============================================================================== 107 | 108 | Updates to ZMP12 Overlays for use with ZMP13. 109 | --------------------------------------------- 110 | 111 | There have been very few changes made to the overlay structure in ZMP13. 112 | Some shuffling of module orders has allowed the origin to be set at 0145 hex, 113 | and here it should stay (unless I fiddle with the startup code -- MOST 114 | unlikely!). So, set your 'userdef' equate to 0145h and you should be able to 115 | leave it there. 116 | There is also a bug fix which should be installed in all overlays. 117 | 118 | 1. Fix a bug in the wait routines 119 | 120 | Two routines in the user overlays are misnamed. You would expect wait1s 121 | to pause for one second, and wait1ms to pause for one millisecond, wouldn't 122 | you? Well they don't. Blame it on a lack of sleep on my part. They actually 123 | pause for a number of seconds (milliseconds) in hl. I suggest renaming them 124 | to waithls amd waithlms. The main consequence of this has been the pause in 125 | the middle of the 'send break' routine: there was originally a ld hl, 1 before 126 | the call to wait1s, but it got lost somewhere along the way. In any case, one 127 | second is probably too long for this, and I suggest you change it to 128 | 129 | ld hl, 300 ; wait 300 mS 130 | call waithlms 131 | 132 | There are two faults in the waithls (formerly wait1s) routine. The first 133 | is a misplaced jr instruction that caused waits of more than 1 second to be 134 | much longer than intended. The other concerns z80 machines with a clock speed 135 | greater than 9 MHz: these will cause 16-bit overflow in the ld de,6667 136 | instruction. (It had never occurred to me that anyone would have a z80 running 137 | at this speed!). Both these faults can be solved by replacing the whole 138 | waithls routine with the following: 139 | 140 | ;Wait seconds in HL 141 | waithls: 142 | push bc ; save bc 143 | push de ; de 144 | push ix ; and ix 145 | ld ix,0 ; then point ix to 0 146 | ; so we don't upset memory-mapped i/o 147 | 148 | ;Calculate values for loop constants. Need to have two loops to avoid 149 | ; 16-bit overflow with clock speeds above 9 MHz. 150 | 151 | outerval equ (clkspd / 10) + 1 152 | innerval equ (6667 / outerval) * clkspd 153 | 154 | wait10: 155 | ld b,outerval 156 | 157 | wait11: 158 | ld de,innerval 159 | 160 | wait12: 161 | bit 0,(ix) ; time-wasters 162 | bit 0,(ix) 163 | bit 0,(ix) ; 20 T-states each 164 | bit 0,(ix) 165 | bit 0,(ix) 166 | bit 0,(ix) 167 | dec de 168 | ld a,e 169 | ld a,d 170 | or e 171 | jr nz,wait12 ; 150 T-states per inner loop 172 | djnz wait11 ; decrement outer loop 173 | dec hl ; ok, decrement count in hl 174 | ld a,h 175 | or l 176 | jr nz,wait10 177 | pop ix ; done -- restore ix 178 | pop de ; de 179 | pop bc ; and bc 180 | ret 181 | 182 | ; End of changes to waithls routine 183 | 184 | The remaining changes concern baud rates. Firstly, ZMP13 will reject a 185 | selected baud rate if the machine is not capable of it. It does this by 186 | determining if the value in mspeed (location 3c hex) has changed. Thus if 187 | you modify your overlay to only change 003ch (mspeed) if the new baud rate 188 | is valid, then incorrect baud rates cannot be selected. No code is given for 189 | this as all overlays are different. Note that the only penalty for not making 190 | this change is that all baud rates are accepted, whether valid or not. Older 191 | overlays always set mspeed to the new value. 192 | In response to numerous requests (well, actually, two), ZMP13 will accept 193 | speeds of 38400, 57600 and 76800 baud. This means that it accepts the numbers 194 | for these -- mspeed values are 10, 11 and 12 respectively. If you think that 195 | you can get your machine to actually work at these speeds, then go ahead. But 196 | don't blame me if it doesn't work. (Personally, I doubt if successful 197 | transfers in both directions with a 4 MHz machine can be done at much over 198 | 4800 baud. But don't let me stop you.) 199 | 200 | -- Ron Murray 201 | 11/10/88 202 | 203 | 204 | End of changes ZMP12 --> ZMP13 205 | =============================================================================== 206 | 207 | Updates to ZMP11 Overlays for ZMP12. 208 | ------------------------------------ 209 | 210 | Some additions to the jump table have been made to allow for user-defined 211 | routines to be executed on entry/exit from ZMP. Modify your overlay as 212 | follows: 213 | 214 | 1. Adding to the jump table 215 | 216 | Add the following code to the end of the jump table after the line: 217 | 218 | jp mswait ; wait milliseconds (Last entry of old table) 219 | 220 | ==> Insert this stuff 221 | jp userin ; user-defined entry routine 222 | jp userout ; user-defined exit routine 223 | 224 | ;Spare jumps for compatibility with future versions 225 | jp spare ; spares for later use 226 | jp spare ; spares for later use 227 | jp spare ; spares for later use 228 | jp spare ; spares for later use 229 | jp spare ; spares for later use 230 | ==> End of inserted jump codes 231 | 232 | 2. Adding the 'spare' code 233 | 234 | The following code can be added anywhere. A good idea is to put the 235 | 'spare:' label in front of an existing ret instruction. 236 | 237 | spare: 238 | ret 239 | 240 | 3. Adding the user routines 241 | 242 | Add the following code to your overlay. Anywhere will do. The code 243 | you put in here depends on what you want to do. 244 | 245 | ;User-defined entry routine: leave empty if not used 246 | userin: 247 | ret 248 | 249 | ;User-defined exit routine: leave empty if not used 250 | userout: 251 | ret 252 | 253 | End of changes ZMP11 --> ZMP12 254 | =============================================================================== 255 | 256 |  -------------------------------------------------------------------------------- /bin/zmp.cfg: -------------------------------------------------------------------------------- 1 | 1 1 0 0 0 360 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | AT! 13 | ATV1Q0DT 14 | ! 15 | CONNECT 16 | BUSY 17 | NO CARRIER 18 | NO ANSWER 19 | ERROR 20 | ~+++~~ATH! 21 | 15 30 22 | 5 N 8 1 23 | 1400 512 F 5 50 24 |  25 | -------------------------------------------------------------------------------- /bin/zmp.fon: -------------------------------------------------------------------------------- 1 | Virtual Altair altair 8 N 8 1 0 2 | _________________ _________________ 9 N 8 1 0 3 | _________________ _________________ 9 N 8 1 0 4 | _________________ _________________ 9 N 8 1 0 5 | _________________ _________________ 9 N 8 1 0 6 | _________________ _________________ 9 N 8 1 0 7 | _________________ _________________ 9 N 8 1 0 8 | heatwave heatwave 8 N 8 1 0 9 | _________________ _________________ 9 N 8 1 0 10 | _________________ _________________ 9 N 8 1 0 11 | _________________ _________________ 9 N 8 1 0 12 | Level 29 bbs.fozztexx.com 8 N 8 1 0 13 | _________________ _________________ 9 N 8 1 0 14 | _________________ _________________ 9 N 8 1 0 15 | _________________ _________________ 9 N 8 1 0 16 | Particles BBS particles 8 N 8 1 0 17 | _________________ _________________ 9 N 8 1 0 18 | _________________ _________________ 9 N 8 1 0 19 | _________________ _________________ 9 N 8 1 0 20 | _________________ _________________ 9 N 8 1 0 21 |  22 | -------------------------------------------------------------------------------- /bin/zmp.for: -------------------------------------------------------------------------------- 1 | ZMP is a communications/file transfer program for CP/M which 2 | performs Xmodem, Xmodem-1k (often erroneously called Ymodem), 3 | true Ymodem and Zmodem file transfer protocols. 4 | 5 | This library contains an un-installed ZMP.COM (called 6 | ZMPX.COM) and five .OVR files. There is also a file called 7 | ZMP-OVL.UPD which describes the changes which need to be made to 8 | the user-written overlay to allow it to operate with this version 9 | of ZMP. YOU need to read this one!! 10 | 11 | Details of changes made to this version are in the ZMPxx.NEW 12 | file. 13 |  -------------------------------------------------------------------------------- /bin/zmp.hlp: -------------------------------------------------------------------------------- 1 | Commands: Precede with ESC: 2 | 3 | B Send break to modem 4 | C Configure system 5 | D Get disk directory 6 | F File operations, change/reset disk 7 | H Get instructions 8 | I Initiate phone call (dial) 9 | K Display keyboard macros 10 | L Change line parameters (baud rate, full/half duplex/echo, UART settings) 11 | M Toggle memory capture mode 12 | P Toggle printer 13 | Q Quit 14 | R Receive a file 15 | S Send a file 16 | X Hangup 17 | Y Print screen 18 | Z Clear local screen 19 | 20 |  -------------------------------------------------------------------------------- /bin/zmp15+-.new: -------------------------------------------------------------------------------- 1 | Version 1.5+/- of ZMP now compiles and links with v3.09 of 2 | Hi Tech C and fixes a few things that had niggled at me for 3 | awhile (some, a few decades): 4 | 5 | * Datestamps transferred in Y/Zmodem transfers. 6 | * Fixed long filename conversions on Y/Zmodem transfers. 7 | * Fixed issues displaying baud rate and send times when the 8 | baud rate is > 19.2K. 9 | * Removed superfluous CR sent to the remote end when a 10 | connection was established, which was a pita when connecting to 11 | a Linux box. 12 | * In keyboard macros, ! translates to a CR now, not CR/LF. 13 | * \ escapes ! and ~ so those literal characters can be used in 14 | keyboard macros. 15 | * Waits in keyboard macros now allow characters from the modem to 16 | be handled. 17 | * Keys in keyboard macros now have 25ms waits between them as to 18 | not overrun the remove system. 19 | * Long distance access code has been removed. 20 | * Quick dialing letters limited to A-T. 21 | 22 | This version, based on the version of the source code in 23 | ZMP-SRC.LBR, is missing a few things that made it into the later 24 | version in ZMP15.LBR. So, to quote the original author, 25 | 26 | "As always, ensure that you erase your .CFG file and make a 27 | new one with the config option. There have again been changes to 28 | the format of this file." 29 | 30 | August 15, 2023 31 |  32 | -------------------------------------------------------------------------------- /bin/zmpx.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/bin/zmpx.com -------------------------------------------------------------------------------- /bin/zmterm.ovr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/bin/zmterm.ovr -------------------------------------------------------------------------------- /bin/zmxfer.ovr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/bin/zmxfer.ovr -------------------------------------------------------------------------------- /hitechc/README.md: -------------------------------------------------------------------------------- 1 | # Hi Tech C replacement files 2 | 3 | After unpacking the Hi Tech C libraries, copy these files 4 | overtop. 5 | -------------------------------------------------------------------------------- /hitechc/cpm.h: -------------------------------------------------------------------------------- 1 | /* header file for CP/M i/o routines for Z-80 C */ 2 | 3 | /* get basic definitions */ 4 | 5 | #ifndef _STDDEF 6 | typedef int ptrdiff_t; /* result type of pointer difference */ 7 | typedef unsigned size_t; /* type yielded by sizeof */ 8 | #define _STDDEF 9 | 10 | #ifndef NULL 11 | #define NULL ((void *)0) 12 | #endif NULL 13 | 14 | extern int errno; /* system error number */ 15 | #endif _STDDEF 16 | 17 | /* hitech.h has definitions for uchar, ushort etc */ 18 | 19 | #include 20 | #if z80 21 | #define MAXFILE 8 /* max number of files open */ 22 | #else z80 23 | #define MAXFILE 15 /* max number of files open */ 24 | #endif z80 25 | #define SECSIZE 128 /* no. of bytes per sector */ 26 | 27 | extern struct fcb { 28 | uchar dr; /* drive code */ 29 | char name[8]; /* file name */ 30 | char ft[3]; /* file type */ 31 | uchar ex; /* file extent */ 32 | char fil[2]; /* not used */ 33 | char rc; /* number of records in present extent */ 34 | char dm[16]; /* CP/M disk map */ 35 | char nr; /* next record to read or write */ 36 | uchar ranrec[3]; /* random record number (24 bit no. ) */ 37 | long rwp; /* read/write pointer in bytes */ 38 | uchar use; /* use flag */ 39 | uchar uid; /* user id belonging to this file */ 40 | } _fcb[MAXFILE]; 41 | 42 | extern char bdos(int, ...); 43 | extern struct fcb * getfcb(void); 44 | extern short bdoshl(int, ...); /* bdos call returning value in hl */ 45 | extern char bios(int, ...); 46 | extern uchar getuid(void); 47 | extern void setuid(int); 48 | extern uchar setfcb(struct fcb *, char *); 49 | 50 | /* flag values in fcb.use */ 51 | 52 | #define U_READ 1 /* file open for reading */ 53 | #define U_WRITE 2 /* file open for writing */ 54 | #define U_RDWR 3 /* open for read and write */ 55 | #define U_CON 4 /* device is console */ 56 | #define U_RDR 5 /* device is reader */ 57 | #define U_PUN 6 /* device is punch */ 58 | #define U_LST 7 /* list device */ 59 | 60 | /* special character values */ 61 | 62 | #define CPMETX 032 /* ctrl-Z, CP/M end of file for text */ 63 | #define CPMRBT 003 /* ctrl-C, reboot CPM */ 64 | 65 | 66 | #define MPM 0x100 /* bit to test for MP/M */ 67 | #define CCPM 0x400 /* bit to test for CCP/M */ 68 | 69 | #define ISMPM() (bdoshl(CPMVERS)&MPM) /* macro to test for MPM */ 70 | 71 | /* what to do after you hit return */ 72 | 73 | #define EXIT (*(int (*)())0) /* where to go to reboot CP/M */ 74 | 75 | /* bdos calls etc. */ 76 | 77 | #define CPMRCON 1 /* read console */ 78 | #define CPMWCON 2 /* write console */ 79 | #define CPMRRDR 3 /* read reader */ 80 | #define CPMWPUN 4 /* write punch */ 81 | #define CPMWLST 5 /* write list */ 82 | #define CPMDCIO 6 /* direct console I/O */ 83 | #define CPMGIOB 7 /* get I/O byte */ 84 | #define CPMSIOB 8 /* set I/O byte */ 85 | #define CPMRCOB 10 /* read console buffered */ 86 | #define CPMICON 11 /* interrogate console ready */ 87 | #define CPMVERS 12 /* return version number */ 88 | 89 | /* BDOS calls */ 90 | 91 | #define CPMRDS 13 /* reset disk system */ 92 | #define CPMLGIN 14 /* log in and select disk */ 93 | #define CPMOPN 15 /* open file */ 94 | #define CPMCLS 16 /* close file */ 95 | #define CPMFFST 17 /* find first */ 96 | #define CPMFNXT 18 /* find next */ 97 | #define CPMDEL 19 /* delete file */ 98 | #define CPMREAD 20 /* read next record */ 99 | #define CPMWRIT 21 /* write next record */ 100 | #define CPMMAKE 22 /* create file */ 101 | #define CPMREN 23 /* rename file */ 102 | #define CPMILOG 24 /* get bit map of logged in disks */ 103 | #define CPMIDRV 25 /* interrogate drive number */ 104 | #define CPMSDMA 26 /* set DMA address for i/o */ 105 | #define CPMGALL 27 /* get allocation vector */ 106 | #define CPMGDPB 31 /* get disk parameter block */ 107 | #define CPMSUID 32 /* set/get user id */ 108 | #define CPMRRAN 33 /* read random record */ 109 | #define CPMWRAN 34 /* write random record */ 110 | #define CPMCFS 35 /* compute file size */ 111 | #define CPMGDFS 46 /* get disk free space */ 112 | #define CPMGZSD 48 /* get ZSDOS indicator */ 113 | #define CPMGSTP 102 /* get file date stamp */ 114 | #define CPMSSTP 103 /* set file date stamp */ 115 |  -------------------------------------------------------------------------------- /hitechc/crtcpm.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/hitechc/crtcpm.obj -------------------------------------------------------------------------------- /hitechc/ctype.h: -------------------------------------------------------------------------------- 1 | #define _U 0x01 2 | #define _L 0x02 3 | #define _N 0x04 4 | #define _S 0x08 5 | #define _P 0x10 6 | #define _C 0x20 7 | #define _X 0x40 8 | 9 | extern unsigned char _ctype_[]; /* in libc.lib */ 10 | 11 | #define isalpha(c) ((_ctype_+1)[c]&(_U|_L)) 12 | #define isupper(c) ((_ctype_+1)[c]&_U) 13 | #define islower(c) ((_ctype_+1)[c]&_L) 14 | #define isdigit(c) ((_ctype_+1)[c]&_N) 15 | #define isxdigit(c) ((_ctype_+1)[c]&(_N|_X)) 16 | #define isspace(c) ((_ctype_+1)[c]&_S) 17 | #define ispunct(c) ((_ctype_+1)[c]&_P) 18 | #define isalnum(c) ((_ctype_+1)[c]&(_U|_L|_N)) 19 | #define isprint(c) ((_ctype_+1)[c]&(_P|_U|_L|_N|_S)) 20 | #define isgraph(c) ((_ctype_+1)[c]&(_P|_U|_L|_N)) 21 | #define iscntrl(c) ((_ctype_+1)[c]&_C) 22 | #define isascii(c) (!((c)&0xFF80)) 23 | #define toupper(c) (islower(c) ? ((c)-'a'+'A') : (c)) 24 | #define tolower(c) (isupper(c) ? ((c)-'A'+'a') : (c)) 25 | #define toascii(c) ((c)&0x7F) 26 |  -------------------------------------------------------------------------------- /hitechc/libc.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/hitechc/libc.lib -------------------------------------------------------------------------------- /hitechc/memset.c: -------------------------------------------------------------------------------- 1 | memset(p, c, n) 2 | register unsigned char *p; 3 | register unsigned char c; 4 | unsigned n; 5 | { 6 | while(n--) 7 | *p++ = c; 8 | } 9 |  -------------------------------------------------------------------------------- /hitechc/mktime.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* leap year calculator expects year argument as years offset from 1900 */ 4 | #define LEAP_YEAR(Y) ( ((1900+(Y))>0) && !((1900+(Y))%4) && ( ((1900+(Y))%100) || !((1900+(Y))%400) ) ) 5 | 6 | static unsigned char monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; 7 | 8 | time_t mktime(struct tm *ptm){ 9 | 10 | int i; 11 | time_t seconds; 12 | 13 | /* seconds from 1970 till 1 jan 00:00:00 of the given year */ 14 | seconds= (ptm->tm_year-70)*(SECS_PER_DAY * 365); 15 | for (i = 70; i < ptm->tm_year; i++) { 16 | if (LEAP_YEAR(i)) { 17 | seconds += SECS_PER_DAY; /* add extra days for leap years */ 18 | } 19 | } 20 | 21 | /* add days for this year */ 22 | for (i = 0; i < ptm->tm_mon; i++) { 23 | if ( (i == 1) && LEAP_YEAR(ptm->tm_year)) { 24 | seconds += SECS_PER_DAY * 29; 25 | } else { 26 | seconds += SECS_PER_DAY * (int)monthDays[i]; 27 | } 28 | } 29 | seconds += (ptm->tm_mday-1) * SECS_PER_DAY; 30 | seconds += ptm->tm_hour * SECS_PER_HOUR; 31 | seconds += ptm->tm_min * SECS_PER_MIN; 32 | seconds += ptm->tm_sec; 33 | seconds += time_zone * SECS_PER_MIN; 34 | return (time_t)seconds; 35 | } 36 |  -------------------------------------------------------------------------------- /hitechc/signal.h: -------------------------------------------------------------------------------- 1 | #ifndef _HTC_SIGNAL_H 2 | #define _HTC_SIGNAL_H 3 | 4 | /* 5 | * Signal definitions for CP/M 6 | */ 7 | #ifdef unix 8 | #define NSIG 17 9 | #define SIGHUP 1 /* hangup (not used by terminal driver) */ 10 | #define SIGINT 2 /* interrupt (^C or BREAK) */ 11 | #define SIGQUIT 3 /* quit (^\) */ 12 | #define SIGILL 4 /* illegal instruction (not reset when caught) */ 13 | #define SIGTRAP 5 /* trace trap (not reset when caught) */ 14 | #define SIGIOT 6 /* IOT instruction */ 15 | #define SIGEMT 7 /* EMT instruction */ 16 | #define SIGFPE 8 /* floating point exception */ 17 | #define SIGKILL 9 /* kill (cannot be caught or ignored) */ 18 | #define SIGBUS 10 /* bus error */ 19 | #define SIGSEGV 11 /* segmentation violation */ 20 | #define SIGSYS 12 /* bad argument to system call */ 21 | #define SIGPIPE 13 /* write on a pipe with no one to read it */ 22 | #define SIGALRM 14 /* alarm clock */ 23 | #define SIGTERM 15 /* software termination signal from kill */ 24 | #else 25 | #define NSIG 1 26 | #define SIGINT 1 /* control-C */ 27 | #endif 28 | 29 | typedef void (*signal_t) (int); 30 | #define SIG_DFL ((signal_t)0) /* default action is to exit */ 31 | #define SIG_IGN ((signal_t)1) /* ignore them */ 32 | 33 | signal_t signal(int sig, signal_t action); 34 | 35 | #endif 36 |  -------------------------------------------------------------------------------- /hitechc/string.h: -------------------------------------------------------------------------------- 1 | /* String functions */ 2 | 3 | #ifndef _STDDEF 4 | typedef int ptrdiff_t; /* result type of pointer difference */ 5 | typedef unsigned size_t; /* type yielded by sizeof */ 6 | #define _STDDEF 7 | #define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) 8 | #endif _STDDEF 9 | 10 | #ifndef NULL 11 | #define NULL ((void *)0) 12 | #endif NULL 13 | 14 | extern int errno; /* system error number */ 15 | 16 | extern void * memcpy(void *, void *, size_t); 17 | extern void * memmove(void *, void *, size_t); 18 | extern char * strcpy(char *, char *); 19 | extern char * strncpy(char *, char *, size_t); 20 | extern char * strcat(char *, char *); 21 | extern char * strncat(char *, char *, size_t); 22 | extern int memcmp(void *, void *, size_t); 23 | extern int strcmp(char *, char *); 24 | extern int strncmp(char *, char *, size_t); 25 | extern size_t strcoll(char *, size_t, char *); 26 | extern void * memchr(void *, int, size_t); 27 | extern size_t strcspn(char *, char *); 28 | extern char * strpbrk(char *, char *); 29 | extern size_t strspn(char *, char *); 30 | extern char * strstr(char *, char *); 31 | extern char * strtok(char *, char *); 32 | extern void * memset(void *, uchar, size_t); 33 | extern char * strerror(int); 34 | extern size_t strlen(char *); 35 | extern char * strchr(char *, int); 36 | extern char * strrchr(char *, int); 37 |  -------------------------------------------------------------------------------- /hitechc/time.h: -------------------------------------------------------------------------------- 1 | #ifndef _TIME 2 | 3 | typedef long time_t; /* for representing times in seconds */ 4 | struct tm { 5 | int tm_sec; 6 | int tm_min; 7 | int tm_hour; 8 | int tm_mday; 9 | int tm_mon; 10 | int tm_year; 11 | int tm_wday; 12 | int tm_yday; 13 | int tm_isdst; 14 | }; 15 | #define _TIME 16 | #endif _TIME 17 | 18 | extern int time_zone; /* minutes WESTWARD of Greenwich */ 19 | /* this value defaults to 0 since with 20 | operating systems like MS-DOS there is 21 | no time zone information available */ 22 | 23 | extern time_t time(time_t *); /* seconds since 00:00:00 Jan 1 1970 */ 24 | extern char * asctime(struct tm *); /* converts struct tm to ascii time */ 25 | extern char * ctime(); /* current local time in ascii form */ 26 | extern struct tm * gmtime(); /* Universal time */ 27 | extern struct tm * localtime(); /* local time */ 28 | extern time_t mktime(struct tm *); 29 | 30 | #define SECS_PER_DAY (86400l) 31 | #define SECS_PER_HOUR (3600l) 32 | #define SECS_PER_MIN (60l) 33 |  -------------------------------------------------------------------------------- /hitechc/zcrtcpm.as: -------------------------------------------------------------------------------- 1 | psect text,global,pure 2 | psect data,global 3 | psect bss,global 4 | 5 | psect text 6 | defs 100h ;Base of CP/M's TPA 7 | 8 | global start,_main,_exit,__Hbss, __Lbss, __argc_, startup 9 | 10 | start: jp start2 11 | defm 'Z3ENV' 12 | defb 1 13 | defw 0 14 | start2: ld hl,(6) ;base address of fdos 15 | ld sp,hl ;stack grows downwards 16 | ld de,__Lbss ;Start of BSS segment 17 | or a ;clear carry 18 | ld hl,__Hbss 19 | sbc hl,de ;size of uninitialized data area 20 | ld c,l 21 | ld b,h 22 | dec bc 23 | ld l,e 24 | ld h,d 25 | inc de 26 | ld (hl),0 27 | ldir ;clear memory 28 | ld hl,nularg 29 | push hl 30 | ld hl,80h ;argument buffer 31 | ld c,(hl) 32 | inc hl 33 | ld b,h ; b = 0 (h was 0) 34 | add hl,bc 35 | ld (hl),b ;zero terminate it (b was 0) 36 | ld hl,81h 37 | push hl 38 | call startup 39 | pop bc ;unjunk stack 40 | pop bc 41 | push hl 42 | ld hl,(__argc_) 43 | push hl 44 | call _main 45 | push hl 46 | call _exit 47 | rst 0 48 | nop ; should be at 0144H 49 | 50 | psect data 51 | nularg: defb 0 52 | end start 53 |  -------------------------------------------------------------------------------- /src/cc.cmd: -------------------------------------------------------------------------------- 1 | IF ~EX $1.OBJ 2 | C -V -O -C $1.C 3 | FI 4 |  -------------------------------------------------------------------------------- /src/makeovl.cmd: -------------------------------------------------------------------------------- 1 | IF ~EX ZMPOVL.HEX 2 | M80 =ZMPOVL 3 | TST M 4 | IF ~ER 5 | RELHEX ZMPOVL 6 | FI 7 | FI 8 | IF EX ZMPOVL.HEX 9 | ERA ZMP.COM 10 | MLOAD ZMP.COM=ZMPX.COM,ZMPOVL 11 | FI 12 |  -------------------------------------------------------------------------------- /src/ovbgn.as: -------------------------------------------------------------------------------- 1 | ; Fake overlay 2 | 3 | 4 | size equ 05000h ; max overlay size 5 | 6 | global _ovbgn, _ovsize, _ovstart 7 | 8 | psect text 9 | 10 | _ovsize: 11 | defw size ; this should never be overlaid 12 | _ovstart: 13 | defw _ovbgn 14 | 15 | psect bss ; this goes in the uninit bit 16 | _ovbgn: 17 | defs size ; reserve room for overlay 18 | 19 | end 20 |  -------------------------------------------------------------------------------- /src/ovloader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern unsigned ovsize; 6 | extern char *ovstart; 7 | extern int ovbgn(int); 8 | 9 | /* Overlay loader for Hi-Tech C */ 10 | ovloader(ovname,args) 11 | char *ovname; 12 | 13 | { 14 | int fd, size, err; 15 | char filename[17], *p; 16 | 17 | strcpy(filename,ovname); /* Copy the filename */ 18 | strcat(filename,".ovr"); /* add the extent */ 19 | if ((fd = open(filename, 0)) < 0) 20 | { 21 | strcpy(filename,"0:A:"); /* not there -- see if it's on A0: */ 22 | strcat(filename, (p = strchr(ovname,':')) ? p+1 : ovname); 23 | strcat(filename,".ovr"); 24 | err = 1; 25 | if ((fd = open(filename,0)) < 0) 26 | goto error; /* Not there either */ 27 | } 28 | size = read(fd,ovstart,ovsize); 29 | close(fd); 30 | err = 2; 31 | if (size < 0) 32 | goto error; /* read error */ 33 | return ovbgn(args); /* ok, execute the overlay */ 34 | 35 | error: 36 | printf("\nError %d in loading %s.ovr\n",err,ovname); 37 | return -1; 38 | } -------------------------------------------------------------------------------- /src/ovrcomp.cmd: -------------------------------------------------------------------------------- 1 | ZCCOMPIL 2 | ZICOMPIL 3 | ZTCOMPIL 4 | ZXCOMPIL 5 |  -------------------------------------------------------------------------------- /src/ovrcomp.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/src/ovrcomp.com -------------------------------------------------------------------------------- /src/userdef.as: -------------------------------------------------------------------------------- 1 | ; Jump table and dummy routines for user-defined stuff 2 | ; 3 | ;Written rjm August, 1988 4 | ; Added setport() rjm 25/3/89 5 | 6 | psect text 7 | 8 | global userdef 9 | global _screenpr,_mrd,_mchin,_mchout,_moutrdy,_mirdy 10 | global _sendbrk,_locate,_cls,_stndout,_getvarsr 11 | global _stndend,_hidecurs,_showcurs,_savecurs,_restcurs 12 | global _minterru,_initvect,_deinitve,_mdmerror,_dtron 13 | global _dtroff,_initace,_wait,_mswait,_userin,_userout 14 | global _getvars,_setport 15 | 16 | ;General equates: 17 | bdos equ 5 18 | cr equ 0dh 19 | lf equ 0ah 20 | 21 | userdef: ; Marker so we know where the overlay starts 22 | 23 | ;Organise as jump table for the overlay 24 | 25 | _screenpr: ; screen print for ZMP, get variables for RZMP 26 | _getvarsr: 27 | jp abort 28 | _mrd: 29 | jp abort 30 | _mchin: 31 | jp abort 32 | _mchout: 33 | jp abort 34 | _moutrdy: 35 | jp abort 36 | _mirdy: 37 | jp abort 38 | _sendbrk: 39 | jp abort 40 | _locate: 41 | jp abort 42 | _cls: 43 | jp abort 44 | _stndout: 45 | jp abort 46 | _stndend: 47 | jp abort 48 | _hidecurs: 49 | jp abort 50 | _showcurs: 51 | jp abort 52 | _savecurs: 53 | jp abort 54 | _restcurs: 55 | jp abort 56 | _minterru: 57 | jp abort 58 | _initvect: 59 | jp abort 60 | _deinitve: 61 | jp abort 62 | _mdmerror: 63 | jp abort 64 | _dtron: 65 | jp abort 66 | _dtroff: 67 | jp abort 68 | _initace: 69 | jp abort 70 | _wait: 71 | jp abort 72 | _mswait: 73 | jp abort 74 | _userin: 75 | jp abort 76 | _userout: 77 | jp abort 78 | _getvars: 79 | jp abort 80 | _setport: 81 | jp abort 82 | 83 | ;Spares 84 | jp abort 85 | jp abort 86 | jp abort 87 | jp abort 88 | jp abort 89 | 90 | 91 | abort: 92 | call print 93 | defb cr,lf 94 | defm 'This copy of ZMP is not installed. Obtain a ' 95 | defm 'suitable overlay for your system.' 96 | defb cr,lf,lf,0 97 | jp 0 ; warm boot 98 | 99 | ;In-line print routine 100 | print: 101 | ex (sp),hl ; get return address 102 | print1: 103 | ld a,(hl) ; get next character 104 | inc hl ; bump pointer 105 | or a ; done if zero 106 | jr nz,print2 107 | ex (sp),hl ; so swap back 108 | ret 109 | print2: 110 | call cout ; ok, print it 111 | jr print1 ; and loop 112 | 113 | ;Print character in A 114 | cout: 115 | push bc 116 | push de 117 | push hl 118 | ld c,2 119 | ld e,a 120 | call bdos 121 | pop hl 122 | pop de 123 | pop bc 124 | ret 125 | 126 | defs 0400h - ($ - userdef) ; Allow room for overlay 127 | 128 |  -------------------------------------------------------------------------------- /src/zccompil.cmd: -------------------------------------------------------------------------------- 1 | CC ZMCONFIG 2 | CC ZMCONF2 3 | CC ZMCONF3 4 | CC ZMCONF4 5 | LINK 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "zmp.h" 13 | 14 | extern char *alloc(int); 15 | extern int allocerror(void *); 16 | extern int chrin(); 17 | extern void cls(); 18 | extern void stndout(); 19 | extern void stndend(); 20 | extern void locate(int,int); 21 | extern void addu(char *,int,int); 22 | 23 | void setparity() 24 | { 25 | int c; 26 | 27 | cls(); 28 | do { 29 | printf("(N)o parity, (O)dd parity, or (E)ven parity? "); 30 | c = chrin(); 31 | if (c>='a' && c<='z') { 32 | c = c - 'a' + 'A'; 33 | } 34 | } while (c != 'N' && c != 'O' && c != 'E' && c != ESC); 35 | if (c=='N' || c=='O' || c=='E') { 36 | Line.parity = c; 37 | } 38 | } 39 | 40 | void setdatabits() 41 | { 42 | int c; 43 | 44 | cls(); 45 | do { 46 | printf("(7) data bits or (8) data bits? "); 47 | c = chrin(); 48 | } while (c != '7' && c != '8' && c != ESC); 49 | if (c=='7' || c=='8') { 50 | Line.databits = c-'0'; 51 | } 52 | } 53 | 54 | void setstopbits() 55 | { 56 | int c; 57 | 58 | cls(); 59 | do { 60 | printf("(1) stop bit or (2) stop bits? "); 61 | c = chrin(); 62 | } while (c != '1' && c != '2' && c != ESC); 63 | if (c=='1' || c=='2') { 64 | Line.stopbits = c-'0'; 65 | } 66 | } 67 | 68 | void cshownos() 69 | { 70 | int i, j; 71 | char echo; 72 | 73 | cls(); 74 | stndout(); 75 | printf(" NAME NUMBER B P D S E"); 76 | stndend(); 77 | for (i = 0, j = 1; i < 20; i++, j++) { 78 | locate(i+1,0); 79 | printf("%c - %s",i+'A',Book[i].name); 80 | printf(" %s",Book[i].number); 81 | locate(i+1,44); 82 | printf("%4u0 %c",Baudtable[Book[i].pbaudindex], 83 | Book[i].pparity); 84 | echo = Book[i].echo ? 'H' : 'F'; 85 | printf(" %d %d %c\n",Book[i].pdatabits,Book[i].pstopbits,echo); 86 | } 87 | } 88 | 89 | int cloadnos() 90 | { 91 | int i,result; 92 | char dummy; 93 | FILE *fd; 94 | unsigned amount; 95 | 96 | result = NERROR; 97 | amount = 21 * sizeof(struct phonebook); 98 | Book = (struct phonebook *)alloc(amount); 99 | if (!allocerror(Book)) { 100 | strcpy(Pathname,Phonefile); 101 | addu(Pathname,Overdrive,Overuser); 102 | fd = fopen(Pathname,"r"); 103 | if (fd!=NULL) { 104 | for (i = 0; i < 20; i++) { 105 | fgets(Book[i].name,17,fd); 106 | fscanf(fd,"%c %s %d %c %d %d %d", 107 | &dummy, 108 | Book[i].number, 109 | &Book[i].pbaudindex, 110 | &Book[i].pparity, 111 | &Book[i].pdatabits, 112 | &Book[i].pstopbits, 113 | &Book[i].echo); 114 | fgetc(fd); /* remove LF */ 115 | } 116 | fclose(fd); 117 | result = OK; 118 | } 119 | } 120 | return result; 121 | } 122 | 123 | /************************* END OF ZMCONFIG MODULE 2 *************************/ 124 |  -------------------------------------------------------------------------------- /src/zmconf3.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* */ 3 | /* Configuration Overlay for ZMP - Module 3 */ 4 | /* */ 5 | /*************************************************************************/ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "zmp.h" 13 | 14 | extern int chrin(); 15 | extern void cls(); 16 | extern int getline(char *,unsigned); 17 | extern void addu(char *,int,int); 18 | extern void wrerror(char *); 19 | extern int cloadnos(); 20 | extern void cshownos(); 21 | 22 | void phonedit() 23 | { 24 | int i, c, change; 25 | char *answer,pad[2]; 26 | 27 | cloadnos(); 28 | answer = Pathname; 29 | for (;;) { 30 | flush(); 31 | cshownos(); 32 | printf("\nEnter letter of phone number to change/enter,\n"); 33 | printf("or anything else to EXIT: "); 34 | c = chrin(); 35 | if (c>='a' && c<='z') { 36 | c = c - 'a' + 'A'; 37 | } 38 | c = c - 'A'; 39 | if (c < 0 || c > 20) { 40 | break; 41 | } 42 | change = TRUE; 43 | flush(); 44 | printf("\n\t\t Name: %s\n\tEnter new name: ", 45 | Book[c].name); 46 | if (getline(answer,18)) { 47 | pad[1] = '\000'; 48 | if (answer[0] == '_') { 49 | pad[0] = '_'; 50 | } else { 51 | pad[0] = ' '; 52 | } 53 | while (strlen(answer) < 17) { 54 | strcat(answer,pad); /* Pad with spaces or underlines */ 55 | } 56 | strcpy(Book[c].name,answer); 57 | } 58 | if (answer[0] != '_') { 59 | printf("\n\t\tNumber: %s\n Enter new number: ", 60 | Book[c].number); 61 | if (getline(answer,18)) { 62 | strcpy(Book[c].number,answer); 63 | } 64 | printf("\n\t Baud rate: %u0\n Enter new baud rate: ", 65 | Baudtable[Book[c].pbaudindex]); 66 | if (getline(answer,18)) { 67 | for (i = 0; i < 13; i++) { 68 | if (atol(answer)/10 == Baudtable[i]) { 69 | Book[c].pbaudindex = i; 70 | break; 71 | } 72 | } 73 | } 74 | printf("\n\t\tParity: %c\n Enter new parity: ", 75 | Book[c].pparity); 76 | if (getline(answer,18)) { 77 | Book[c].pparity = toupper(answer[0]); 78 | } 79 | printf("\n\t # data bits: %d\n Enter new number: ", 80 | Book[c].pdatabits); 81 | if (getline(answer,18)) { 82 | Book[c].pdatabits = atoi(answer); 83 | } 84 | printf("\n\t # stop bits: %d\n Enter new number: ", 85 | Book[c].pstopbits); 86 | if (getline(answer,18)) { 87 | Book[c].pstopbits = atoi(answer); 88 | } 89 | printf("\n\t\tDuplex: %s\nEnter (H)alf or (F)ull: ", 90 | Book[c].echo?"Half":"Full"); 91 | if (getline(answer,18)) { 92 | Book[c].echo = answer[0] == 'H' || answer[0] == 'h'; 93 | } 94 | } else { 95 | strcpy(Book[c].number,"_________________"); 96 | Book[c].pbaudindex = 5; /* default to 1200 baud */ 97 | Book[c].pparity = 'N'; 98 | Book[c].pdatabits = 8; 99 | Book[c].pstopbits = 1; 100 | Book[c].echo = FALSE; 101 | } 102 | } 103 | flush(); 104 | cls(); 105 | if (Book != (struct phonebook *)MEMORY_FULL) { 106 | free(Book); 107 | } 108 | } 109 | 110 | void savephone() 111 | { 112 | int i; 113 | FILE *fd; 114 | 115 | strcpy(Pathname,Phonefile); 116 | addu(Pathname,Overdrive,Overuser); 117 | fd = fopen(Pathname,"w"); 118 | if (fd) { 119 | printf("\nSaving Phone numbers..."); 120 | for (i = 0; i < 20; i++) { 121 | fprintf(fd,"%s %s %d %c %d %d %d\n", 122 | Book[i].name, 123 | Book[i].number, 124 | Book[i].pbaudindex, 125 | Book[i].pparity, 126 | Book[i].pdatabits, 127 | Book[i].pstopbits, 128 | Book[i].echo); 129 | } 130 | fclose(fd); 131 | printf("Successful.\n"); 132 | } else { 133 | wrerror(Phonefile); 134 | } 135 | } 136 | 137 | /************************* END OF ZMCONFIG MODULE 3 *************************/ 138 |  -------------------------------------------------------------------------------- /src/zmconf4.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* */ 3 | /* Configuration Overlay for ZMP - Module 4 */ 4 | /* */ 5 | /*************************************************************************/ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "zmp.h" 14 | 15 | extern int chrin(); 16 | extern void cls(); 17 | extern int getline(char *,unsigned); 18 | extern void stndout(); 19 | extern void stndend(); 20 | extern void addu(char *,int,int); 21 | extern void wrerror(char *); 22 | 23 | void edit() 24 | { 25 | int i; 26 | char *buffer; 27 | char key; 28 | 29 | buffer = Pathname; 30 | do { 31 | cls(); 32 | flush(); 33 | printf("\r\t\t"); 34 | stndout(); 35 | puts(" KEYPAD MACRO LIST \n"); 36 | stndend(); 37 | for (i=0; i<10; i++) { 38 | printf("%d - %s\n",i,KbMacro[i]); 39 | } 40 | printf("\nPress key of macro to edit, esc to quit: "); 41 | key = (char)chrin(); 42 | if (isdigit(key)) { 43 | i = key-'0'; 44 | flush(); 45 | puts("\nIf you want the macro to end with a RETURN,"); 46 | puts("add a '\041' to the end of your entry (20 chars. max).\n"); 47 | printf("Old Macro: "); 48 | puts(KbMacro[i]); 49 | printf("\nNew Macro: "); 50 | if (getline(buffer,21)) { 51 | strcpy(KbMacro[i],buffer); 52 | } 53 | } 54 | } while (isdigit(key)); 55 | flush(); 56 | } 57 | 58 | void saveconfig() 59 | { 60 | int i; 61 | FILE *fd; 62 | 63 | strcpy(Pathname,Cfgfile); 64 | addu(Pathname,Overdrive,Overuser); 65 | fd = fopen(Pathname,"w"); 66 | if (fd) { 67 | printf("\n\nSaving Configuration..."); 68 | fprintf(fd,"%d %d %d %d %d %d\n",Crcflag,Wantfcs32, 69 | XonXoff,Filter,ParityMask,time_zone); 70 | for (i = 0; i < 10; i++) 71 | fprintf(fd,"%s\n",KbMacro[i]); 72 | fprintf(fd,"%s\n%s\n%s\n",Modem.init,Modem.dialcmd, 73 | Modem.dialsuffix); 74 | fprintf(fd,"%s\n%s\n%s\n",Modem.connect,Modem.busy1, 75 | Modem.busy2); 76 | fprintf(fd,"%s\n%s\n%s\n",Modem.busy3,Modem.busy4, 77 | Modem.hangup); 78 | fprintf(fd,"%d %d\n",Modem.timeout,Modem.pause); 79 | fprintf(fd,"%d %c %d %d\n",Line.baudindex,Line.parity, 80 | Line.databits,Line.stopbits); 81 | fprintf(fd,"%d %u %c %d %d\n",Zrwindow,Pbufsiz,Maxdrive, 82 | Chardelay,Linedelay); 83 | fclose(fd); 84 | printf("Successful.\n"); 85 | } else { 86 | wrerror(Cfgfile); 87 | } 88 | } 89 | 90 | /************************* END OF ZMCONFIG MODULE 4 *************************/ 91 |  -------------------------------------------------------------------------------- /src/zmconfig.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* */ 3 | /* Configuration Overlay for ZMP - Module 1 */ 4 | /* */ 5 | /*************************************************************************/ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "zmp.h" 12 | 13 | extern void cls(); 14 | extern void stndout(); 15 | extern void etndend(); 16 | extern int getline(char *,unsigned); 17 | extern int chrin(); 18 | extern void setparity(); 19 | extern void setdatabits(); 20 | extern void setstopbits(); 21 | extern void phonedit(); 22 | extern void edit(); 23 | extern void savephone(); 24 | extern void saveconfig(); 25 | 26 | extern int time_zone; 27 | 28 | static void settransfer(); 29 | static void setsys(); 30 | static void setmodem(); 31 | static void gnewint(char *, int *); 32 | static void gnewstr(char *, char *, short); 33 | static void setline(); 34 | static void setbaud(); 35 | static int goodbaud(unsigned); 36 | 37 | ovmain() 38 | { 39 | int c, cfgchanged, phonechanged; 40 | 41 | cfgchanged = phonechanged = FALSE; 42 | 43 | for (;;) { 44 | cls(); 45 | printf("\r\t\t"); 46 | stndout(); 47 | printf(" CONFIGURATION MENU "); 48 | stndend(); 49 | 50 | printf("\n\n\tK - Edit keyboard macros\n"); 51 | printf("\tL - Set line parameters\n"); 52 | printf("\tM - Set modem parameters\n"); 53 | printf("\tP - Edit phone number list\n"); 54 | printf("\tS - Set system parameters\n"); 55 | printf("\tT - Set file transfer parameters\n"); 56 | printf("\tZ - Exit\n"); 57 | printf("\n Select: "); 58 | flush(); 59 | c = chrin(); 60 | c = toupper(c); 61 | switch (c) { 62 | 63 | case 'K': 64 | edit(); 65 | cfgchanged = TRUE; 66 | break; 67 | 68 | case 'L': 69 | setline(); 70 | cfgchanged = TRUE; 71 | break; 72 | 73 | case 'M': 74 | setmodem(); 75 | cfgchanged = TRUE; 76 | break; 77 | 78 | case 'P': 79 | phonedit(); 80 | phonechanged = TRUE; 81 | break; 82 | 83 | case 'S': 84 | setsys(); 85 | cfgchanged = TRUE; 86 | break; 87 | 88 | case 'T': 89 | settransfer(); 90 | cfgchanged = TRUE; 91 | break; 92 | 93 | case ESC: 94 | case 'Z': 95 | if (cfgchanged || phonechanged) { 96 | printf("\nMake changes permanent? "); 97 | c = chrin(); 98 | c = toupper(c); 99 | if (c == 'Y') { 100 | if (cfgchanged) { 101 | saveconfig(); 102 | } 103 | if (phonechanged) { 104 | savephone(); 105 | } 106 | kbwait(2); 107 | } 108 | } 109 | cls(); 110 | return; /* Return from overlay */ 111 | 112 | default: 113 | break; 114 | 115 | } /* end of switch */ 116 | } 117 | } 118 | 119 | static void settransfer() 120 | { 121 | int c; 122 | 123 | for (;;) { 124 | cls(); 125 | printf("\r\t\t\t"); 126 | stndout(); 127 | printf(" FILE TRANSFER PARAMETERS "); 128 | stndend(); 129 | printf("\n\n\tC - Set Checksum/CRC default - now %s\n", 130 | Crcflag?"CRC":"Checksum"); 131 | printf("\tD - Set delay after each character in ASCII send - now %d mS\n", 132 | Chardelay); 133 | printf("\tF - Toggle 32-bit FCS capability - now %s\n", 134 | Wantfcs32?"Enabled":"Disabled"); 135 | printf("\tL - Set delay after each line in ASCII send - now %d mS\n", 136 | Linedelay); 137 | printf("\tW - Change Zmodem receive window size - now %d\n",Zrwindow); 138 | printf("\tX - Toggle X-on/X-off protocol - now %s\n", 139 | XonXoff?"Enabled":"Disabled"); 140 | printf("\tZ - Exit\n\n"); 141 | printf(" Select: "); 142 | c = chrin(); 143 | c = toupper(c); 144 | putchar('\n'); 145 | switch (c) { 146 | case 'C': 147 | Crcflag = !Crcflag; 148 | break; 149 | 150 | case 'D': 151 | gnewint("character delay",&Chardelay); 152 | break; 153 | 154 | case 'F': 155 | Wantfcs32 = !Wantfcs32; 156 | break; 157 | 158 | case 'L': 159 | gnewint("line delay",&Linedelay); 160 | break; 161 | 162 | case 'W': 163 | gnewint("window size",&Zrwindow); 164 | break; 165 | 166 | case 'X': 167 | XonXoff = !XonXoff; 168 | break; 169 | 170 | case ESC: 171 | case 'Z': 172 | return; 173 | 174 | default: 175 | break; 176 | } 177 | } 178 | } 179 | 180 | static void setsys() 181 | { 182 | int c; 183 | char d; 184 | 185 | for (;;) { 186 | cls(); 187 | printf("\r\t\t\t"); 188 | stndout(); 189 | printf(" SYSTEM PARAMETERS "); 190 | stndend(); 191 | printf("\n\n\tB - Set print buffer size - now %d bytes\n",Pbufsiz); 192 | printf("\tF - Toggle T-mode control character filter - now %s\n", 193 | Filter ? "ON" : "OFF"); 194 | printf("\tM - Set maximum drive on system - now %c:\n",Maxdrive); 195 | printf("\tP - Toggle T-mode parity bit removal - now %s\n", 196 | ParityMask ? "ON" : "OFF"); 197 | printf("\tT - Set minutes west of UTC - now %d\n",time_zone); 198 | printf("\tZ - Exit\n\n"); 199 | printf(" Select: "); 200 | c = chrin(); 201 | c = toupper(c); 202 | switch (c) { 203 | 204 | case 'B': 205 | gnewint("print buffer size",&Pbufsiz); 206 | Pbufsiz = Pbufsiz < 1 ? 512 : Pbufsiz; 207 | break; 208 | 209 | case 'F': 210 | Filter = !Filter; 211 | break; 212 | 213 | case 'M': 214 | printf("\n\nEnter new maximum drive: "); 215 | d = chrin(); 216 | d = toupper(d); 217 | Maxdrive = ((d >= 'A') && (d <= 'P')) ? d : 'B'; 218 | break; 219 | 220 | case 'P': 221 | ParityMask = !ParityMask; 222 | break; 223 | 224 | case 'T': 225 | gnewint("minutes west of UTC",&time_zone); 226 | break; 227 | 228 | case ESC: 229 | case 'Z': 230 | return; 231 | 232 | default: 233 | break; 234 | } 235 | } 236 | } 237 | 238 | static char *Mdmstring[] = { 239 | "Modem init string.....", 240 | "Dialling command......", 241 | "Dial command suffix...", 242 | "Connect string........", 243 | "No Connect string 1...", 244 | "No Connect string 2...", 245 | "No Connect string 3...", 246 | "No Connect string 4...", 247 | "Hangup string.........", 248 | "Redial timeout delay..", 249 | "Redial pause delay...." 250 | }; 251 | 252 | static void setmodem() 253 | { 254 | int c; 255 | 256 | for (;;) { 257 | cls(); 258 | printf("\r\t\t\t"); 259 | stndout(); 260 | printf(" MODEM PARAMETERS "); 261 | stndend(); 262 | printf("\n\n\tA - %s%s\n",Mdmstring[0],Modem.init); 263 | printf("\tB - %s%s\n",Mdmstring[1],Modem.dialcmd); 264 | printf("\tC - %s%s\n",Mdmstring[2],Modem.dialsuffix); 265 | printf("\tD - %s%s\n",Mdmstring[3],Modem.connect); 266 | printf("\tE - %s%s\n",Mdmstring[4],Modem.busy1); 267 | printf("\tF - %s%s\n",Mdmstring[5],Modem.busy2); 268 | printf("\tG - %s%s\n",Mdmstring[6],Modem.busy3); 269 | printf("\tH - %s%s\n",Mdmstring[7],Modem.busy4); 270 | printf("\tI - %s%s\n",Mdmstring[8],Modem.hangup); 271 | printf("\tJ - %s%d\n",Mdmstring[9],Modem.timeout); 272 | printf("\tK - %s%d\n",Mdmstring[10],Modem.pause); 273 | printf("\tZ - Exit\n\n"); 274 | printf(" Select: "); 275 | c = chrin(); 276 | c = toupper(c); 277 | putchar('\n'); 278 | switch (c) { 279 | 280 | case 'A': 281 | gnewstr(Mdmstring[0],Modem.init,40); 282 | break; 283 | 284 | case 'B': 285 | gnewstr(Mdmstring[1],Modem.dialcmd,20); 286 | break; 287 | 288 | case 'C': 289 | gnewstr(Mdmstring[2],Modem.dialsuffix,20); 290 | break; 291 | 292 | case 'D': 293 | gnewstr(Mdmstring[3],Modem.connect,20); 294 | break; 295 | 296 | case 'E': 297 | gnewstr(Mdmstring[4],Modem.busy1,20); 298 | break; 299 | 300 | case 'F': 301 | gnewstr(Mdmstring[5],Modem.busy2,20); 302 | break; 303 | 304 | case 'G': 305 | gnewstr(Mdmstring[6],Modem.busy3,20); 306 | break; 307 | 308 | case 'H': 309 | gnewstr(Mdmstring[7],Modem.busy4,20); 310 | break; 311 | 312 | case 'I': 313 | gnewstr(Mdmstring[8],Modem.hangup,20); 314 | break; 315 | 316 | case 'J': 317 | gnewint(Mdmstring[9],&Modem.timeout); 318 | break; 319 | 320 | case 'K': 321 | gnewint(Mdmstring[10],&Modem.pause); 322 | break; 323 | 324 | case ESC: 325 | case 'Z': 326 | return; 327 | 328 | default: 329 | break; 330 | } 331 | } 332 | } 333 | 334 | static void gnewint(prompt,intp) 335 | char *prompt; 336 | int *intp; 337 | { 338 | static char *temp; 339 | 340 | temp = Pathname; 341 | printf("\n\nEnter new %s: ",prompt); 342 | if (getline(temp,20)) { 343 | *intp = atoi(temp); 344 | } 345 | } 346 | 347 | static void gnewstr(prompt,mstring,length) 348 | char *prompt, *mstring; 349 | short length; 350 | { 351 | char *temp; 352 | 353 | temp = Pathname; 354 | printf("\n\nEnter new %s: ",prompt); 355 | if (getline(temp,length)) { 356 | strcpy(mstring,temp); 357 | } 358 | } 359 | 360 | static void setline() 361 | { 362 | int c; 363 | 364 | for (;;) { 365 | cls(); 366 | printf("\r\t\t\t"); 367 | stndout(); 368 | printf(" LINE PARAMETERS "); 369 | stndend(); 370 | printf("\n\n\tB - Bits per second.......%u0\n", 371 | Baudtable[Line.baudindex]); 372 | printf("\tD - Number data bits......%d\n",Line.databits); 373 | printf("\tP - Parity................%c\n",Line.parity); 374 | printf("\tS - Number stop bits......%d\n",Line.stopbits); 375 | printf("\tZ - Exit\n\n"); 376 | printf(" Select: "); 377 | c = chrin(); 378 | c = toupper(c); 379 | cls(); 380 | switch (c) { 381 | case 'B': 382 | setbaud(); 383 | break; 384 | 385 | case 'D': 386 | setdatabits(); 387 | break; 388 | 389 | case 'P': 390 | setparity(); 391 | break; 392 | 393 | case 'S': 394 | setstopbits(); 395 | break; 396 | 397 | case ESC: 398 | case 'Z': 399 | return; 400 | 401 | default: 402 | break; 403 | } 404 | } 405 | } 406 | 407 | static void setbaud() 408 | { 409 | unsigned baud; 410 | char *buffer; 411 | 412 | buffer = Pathname; 413 | do { 414 | printf("\nEnter default modem bit rate: "); 415 | if (!(getline(buffer,6))) 416 | break; 417 | baud = (unsigned)(atol(buffer)/10); 418 | printf("\n"); 419 | } while (!goodbaud(baud)); 420 | } 421 | 422 | static int goodbaud(value) 423 | unsigned value; 424 | { 425 | int i; 426 | 427 | for (i = 0; i < 14; i++) { 428 | if (value == Baudtable[i]) { 429 | Line.baudindex = i; 430 | return TRUE; 431 | } 432 | } 433 | printf("\nInvalid entry\n"); 434 | wait(1); 435 | return FALSE; 436 | } 437 | 438 | /********************** END OF ZMCONFIG MODULE 1 ****************************/ 439 |  -------------------------------------------------------------------------------- /src/zmconfig.lnk: -------------------------------------------------------------------------------- 1 | -c40d2h -ptext=40d2h,data -ozmconfig.ovr -mzmconfig.map zmconfig.obj \ 2 | zmconf2.obj zmconf3.obj zmconf4.obj main.obj a:libx.lib a:libc.lib 3 |  -------------------------------------------------------------------------------- /src/zminit.c: -------------------------------------------------------------------------------- 1 | /******************** Initialisation Overlay for ZMP ***********************/ 2 | 3 | #define INIT 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "zmp.h" 9 | 10 | extern void userin(); 11 | extern void initvect(); 12 | extern void initcurs(); 13 | extern void showcurs(); 14 | extern void cls(); 15 | extern void locate(int,int); 16 | extern int ctr(char *); 17 | extern int readline(int); 18 | 19 | static void title(); 20 | static void getconfig(); 21 | static void initializemodem(); 22 | static void xfgets(char *,int,FILE *); 23 | static void resetace(); 24 | 25 | ovmain() 26 | { 27 | unsigned u; 28 | 29 | userin(); /* perform user-defined entry routine */ 30 | title(); 31 | getconfig(); 32 | initvect(); /* set up interrupt vector */ 33 | u = (unsigned) *Mspeed; 34 | if ( !u || u > 13 ) { 35 | initializemodem(); /* initialise uart as well */ 36 | } else { 37 | Current.cbaudindex = (int) (*Mspeed); 38 | Current.cparity = Line.parity; /* Only update */ 39 | Current.cdatabits = Line.databits; /* internal */ 40 | Current.cstopbits = Line.stopbits; /* variables */ 41 | } 42 | ZsDos = (bdoshl(CPMGZSD) & 0xFF00)>>8 == 'S'; 43 | Currdrive = Invokdrive; 44 | Curruser = Invokuser; 45 | reset(Currdrive,Curruser); 46 | showcurs(); 47 | } 48 | 49 | 50 | static void title() 51 | { 52 | static char line1[] = "ZMP - A ZMODEM Program for CP/M"; 53 | static char line3[] = "Developed from HMODEM II"; 54 | static char line4[] = "by Ron Murray"; 55 | static char line5[] = "Updated to Hi Tech C v3.09"; 56 | static char line6[] = "by Wayne Hortensius"; 57 | 58 | cls(); 59 | locate(7,ctr(line1)); 60 | printf(line1); 61 | locate(9,ctr(Version)); 62 | printf(Version); 63 | locate(10,ctr(line3)); 64 | printf(line3); 65 | locate(11,ctr(line4)); 66 | printf(line4); 67 | locate(13,ctr(line5)); 68 | printf(line5); 69 | locate(14,ctr(line6)); 70 | printf(line6); 71 | locate(14,0); 72 | hidecurs(); 73 | flush(); 74 | } 75 | 76 | /* Initialise the modem */ 77 | static void initializemodem() 78 | { 79 | resetace(); 80 | mstrout("\r\r",FALSE); 81 | mstrout(Modem.init,FALSE); 82 | while(readline(10) != TIMEOUT); /* gobble echoed characters */ 83 | } 84 | 85 | /* Read the .CFG file into memory */ 86 | static void getconfig() 87 | { 88 | int i; 89 | FILE *fd; 90 | 91 | strcpy(Pathname,Cfgfile); 92 | addu(Pathname,Overdrive,Overuser); 93 | fd = fopen(Pathname,"rb"); 94 | if (fd) { 95 | fscanf( 96 | fd,"%d %d %d %d %d %d",&Crcflag,&Wantfcs32,&XonXoff,&Filter,&ParityMask,&time_zone); 97 | for (i = 0; i < 10; i++) { 98 | xfgets(KbMacro[i],22,fd); 99 | } 100 | xfgets(Modem.init,40,fd); 101 | xfgets(Modem.dialcmd,8,fd); 102 | xfgets(Modem.dialsuffix,8,fd); 103 | xfgets(Modem.connect,20,fd); 104 | xfgets(Modem.busy1,20,fd); 105 | xfgets(Modem.busy2,20,fd); 106 | xfgets(Modem.busy3,20,fd); 107 | xfgets(Modem.busy4,20,fd); 108 | xfgets(Modem.hangup,20,fd); 109 | fscanf(fd,"%d %d",&Modem.timeout,&Modem.pause); 110 | fscanf(fd,"%d %c %d %d",&Line.baudindex,&Line.parity, 111 | &Line.databits,&Line.stopbits); 112 | fscanf(fd,"%d %d %c %d %d",&Zrwindow,&Pbufsiz,&Maxdrive, 113 | &Chardelay,&Linedelay); 114 | fclose(fd); 115 | } 116 | } 117 | 118 | /* Read a string from a file and remove the newline characters */ 119 | static void xfgets(buf,max,fd) 120 | char *buf; 121 | int max; 122 | FILE *fd; 123 | { 124 | short noerror = 1; 125 | char *p, *index(); 126 | char tbuf[81]; 127 | 128 | tbuf[0] = '\0'; 129 | while (!strlen(tbuf) && noerror) { 130 | noerror = (short) fgets(tbuf,80,fd); 131 | while ( p = index(tbuf,'\12')) { 132 | strcpy(p, p + 1); 133 | } 134 | while ( p = index(tbuf,'\15')) { 135 | strcpy(p, p + 1); 136 | } 137 | } 138 | strncpy(buf,tbuf,max); 139 | } 140 | 141 | static void resetace() /* to default values */ 142 | { 143 | Current.cparity = Line.parity; 144 | Current.cdatabits = Line.databits; 145 | Current.cstopbits = Line.stopbits; 146 | Current.cbaudindex = Line.baudindex; 147 | initace( 148 | Current.cbaudindex, 149 | Current.cparity, 150 | Current.cdatabits, 151 | Current.cstopbits); 152 | } 153 | 154 | /* End of initialisation overlay */ 155 |  -------------------------------------------------------------------------------- /src/zminit.lnk: -------------------------------------------------------------------------------- 1 | -c40d2h -ptext=40d2h,data -ozminit.ovr -mzminit.map zminit.obj main.obj \ 2 | a:libx.lib a:libc.lib 3 |  -------------------------------------------------------------------------------- /src/zmodmdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Z M O D E M . H Manifest constants for ZMODEM 3 | * application to application file transfer protocol 4 | * 05-23-87 Chuck Forsberg Omen Technology Inc 5 | * 12-10-87 Modified by HM for cpm 6 | */ 7 | 8 | /* Leave most of this file alone. If your system can buffer incoming 9 | * characters, and/or can receive data during disk i/o, and/or send 10 | * a break signal, you can try changing the ZRINIT bit masks. 11 | * 12 | */ 13 | 14 | /********************* zmodem defines ***************************************/ 15 | 16 | #define ZPAD '*' /* 052 Padding character begins frames */ 17 | #define ZDLE 030 /* Ctrl-X Zmodem escape - `ala BISYNC DLE */ 18 | #define ZDLEE (ZDLE^0100) /* Escaped ZDLE as transmitted */ 19 | #define ZBIN 'A' /* Binary frame indicator */ 20 | #define ZHEX 'B' /* HEX frame indicator */ 21 | #define ZBIN32 'C' /* Binary frame with 32 bit FCS */ 22 | 23 | /* Frame types (see array "frametypes" in zm.c) */ 24 | 25 | #define ZRQINIT 0 /* Request receive init */ 26 | #define ZRINIT 1 /* Receive init */ 27 | #define ZSINIT 2 /* Send init sequence (optional) */ 28 | #define ZACK 3 /* ACK to above */ 29 | #define ZFILE 4 /* File name from sender */ 30 | #define ZSKIP 5 /* To sender: skip this file */ 31 | #define ZNAK 6 /* Last packet was garbled */ 32 | #define ZABORT 7 /* Abort batch transfers */ 33 | #define ZFIN 8 /* Finish session */ 34 | #define ZRPOS 9 /* Resume data trans at this position */ 35 | #define ZDATA 10 /* Data packet(s) follow */ 36 | #define ZEOF 11 /* End of file */ 37 | #define ZFERR 12 /* Fatal Read or Write error Detected */ 38 | #define ZCRC 13 /* Request for file CRC and response */ 39 | #define ZCHALLENGE 14 /* Receiver's Challenge */ 40 | #define ZCOMPL 15 /* Request is complete */ 41 | #define ZCAN 16 /* Other end canned session with CAN*5 */ 42 | #define ZFREECNT 17 /* Request for free bytes on filesystem */ 43 | #define ZCOMMAND 18 /* Command from sending program */ 44 | #define ZSTDERR 19 /* Output to standard error, data follows */ 45 | 46 | /* ZDLE sequences */ 47 | 48 | #define ZCRCE 'h' /* CRC next, frame ends, header packet follows */ 49 | #define ZCRCG 'i' /* CRC next, frame continues nonstop */ 50 | #define ZCRCQ 'j' /* CRC next, frame continues, ZACK expected */ 51 | #define ZCRCW 'k' /* CRC next, ZACK expected, end of frame */ 52 | #define ZRUB0 'l' /* Translate to rubout 0177 */ 53 | #define ZRUB1 'm' /* Translate to rubout 0377 */ 54 | 55 | /* zdlread return values (internal) */ 56 | /* -1 is general error, -2 is timeout */ 57 | 58 | #define GOTOR 0400 59 | #define GOTCRCE (ZCRCE|GOTOR) /* ZDLE-ZCRCE received */ 60 | #define GOTCRCG (ZCRCG|GOTOR) /* ZDLE-ZCRCG received */ 61 | #define GOTCRCQ (ZCRCQ|GOTOR) /* ZDLE-ZCRCQ received */ 62 | #define GOTCRCW (ZCRCW|GOTOR) /* ZDLE-ZCRCW received */ 63 | #define GOTCAN (GOTOR|030) /* CAN*5 seen */ 64 | 65 | /* Byte positions within header array */ 66 | #define ZF0 3 /* First flags byte */ 67 | #define ZF1 2 68 | #define ZF2 1 69 | #define ZF3 0 70 | #define ZP0 0 /* Low order 8 bits of position */ 71 | #define ZP1 1 72 | #define ZP2 2 73 | #define ZP3 3 /* High order 8 bits of file position */ 74 | 75 | /* Bit Masks for ZRINIT flags byte ZF0 */ 76 | /* Change to suit your system. These are initially set for the simplest */ 77 | /* possible case. Set to 0 to disable, set to values in () to enable */ 78 | 79 | #define CANFDX 0 /* Rx can send and receive true FDX (01) */ 80 | #define CANOVIO 0 /* Rx can receive data during disk I/O (02) */ 81 | #define CANBRK 0 /* Rx can send a break signal (04) */ 82 | #define CANCRY 010 /* Receiver can decrypt */ 83 | #define CANLZW 020 /* Receiver can uncompress */ 84 | #define CANFC32 040 /* Receiver can use 32 bit Frame Check */ 85 | #define ESCCTL 0100 /* Receiver expects ctl chars to be escaped */ 86 | #define ESC8 0200 /* Receiver expects 8th bit to be escaped */ 87 | 88 | /* Parameters for ZSINIT frame */ 89 | 90 | #define ZATTNLEN 32 /* Max length of attention string */ 91 | 92 | /* Bit Masks for ZSINIT flags byte ZF0 */ 93 | 94 | #define TESCCTL 0100 /* Transmitter expects ctl chars to be escaped */ 95 | #define TESC8 0200 /* Transmitter expects 8th bit to be escaped */ 96 | 97 | /* Parameters for ZFILE frame */ 98 | /* Conversion options one of these in ZF0 */ 99 | 100 | #define ZCBIN 1 /* Binary transfer - inhibit conversion */ 101 | #define ZCNL 2 /* Convert NL to local end of line convention */ 102 | #define ZCRESUM 3 /* Resume interrupted file transfer */ 103 | 104 | /* Management include options, one of these ored in ZF1 */ 105 | 106 | #define ZMSKNOLOC 0200 /* Skip file if not present at rx */ 107 | 108 | /* Management options, one of these ored in ZF1 */ 109 | 110 | #define ZMMASK 037 /* Mask for the choices below */ 111 | #define ZMNEWL 1 /* Transfer if source newer or longer */ 112 | #define ZMCRC 2 /* Transfer if different file CRC or length */ 113 | #define ZMAPND 3 /* Append contents to existing file (if any) */ 114 | #define ZMCLOB 4 /* Replace existing file */ 115 | #define ZMNEW 5 /* Transfer if source newer */ 116 | 117 | /* Number 5 is alive ... */ 118 | 119 | #define ZMDIFF 6 /* Transfer if dates or lengths different */ 120 | #define ZMPROT 7 /* Protect destination file */ 121 | 122 | /* Transport options, one of these in ZF2 */ 123 | 124 | #define ZTLZW 1 /* Lempel-Ziv compression */ 125 | #define ZTCRYPT 2 /* Encryption */ 126 | #define ZTRLE 3 /* Run Length encoding */ 127 | 128 | /* Extended options for ZF3, bit encoded */ 129 | 130 | #define ZXSPARS 64 /* Encoding for sparse file operations */ 131 | 132 | /* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */ 133 | 134 | #define ZCACK1 1 /* Acknowledge, then do command */ 135 | 136 | #define INTRATIME 50 /* intra-packet wait time */ 137 | 138 | #define FRTYPES 21 /* Total number of frame types in this array */ 139 | /* not including psuedo negative entries */ 140 | #define FTOFFSET 3 141 | /******************* End of ZMODEM.H ****************************************/ 142 |  -------------------------------------------------------------------------------- /src/zmp.h: -------------------------------------------------------------------------------- 1 | /****************************** zmp.h *************************************/ 2 | 3 | #define FALSE 0 4 | #define TRUE 1 5 | 6 | #define MAXOVLY 0x5100 /* Largest overlay size */ 7 | 8 | #ifndef MAIN 9 | #define EXTERN extern 10 | #else 11 | #define EXTERN 12 | #endif 13 | 14 | #undef ZCPR3 /* #define if using zcpr3 */ 15 | 16 | /* Make allowances for the vagaries of different C compilers (sigh!) */ 17 | 18 | #define MEMORY_FULL 0 19 | #define NBDOS bdoshl 20 | 21 | #define PBUFSIZ 2048 /*2k printer buffer*/ 22 | #define DFLTINDEX 5 /* pointer to default baud */ 23 | 24 | /*************************************************************************/ 25 | /* */ 26 | /* These #defines determine which keys will be interpreted as */ 27 | /* command characters. */ 28 | /* */ 29 | /*************************************************************************/ 30 | 31 | #define RECEIVE 'R' /*receive file*/ 32 | #define CAPTURE 'M' /*toggle capture mode*/ 33 | #define DIR 'D' /*get disk directory*/ 34 | #define PRTSCRN 'Y' /*print screen*/ 35 | #define SEND 'S' /*send file*/ 36 | #define HANGUP 'X' /*hangup*/ 37 | #define COMMAND 'L' /*change line parameters*/ 38 | #define HELP 'H' /*get instructions*/ 39 | #define QUIT 'Q' /*quit*/ 40 | #define DIAL 'I' /*make phone call*/ 41 | #define HOST 'O' /* host mode */ 42 | #define CONFIG 'C' /*configure system*/ 43 | #define TOGPRT 'P' /*toggle printer*/ 44 | #define DISK 'F' /*file/disk operations*/ 45 | #define CLRSCR 'Z' /*clear local screen*/ 46 | #define BRK 'B' /*send break*/ 47 | #define DISPKEYS 'K' /*display keyboard macros*/ 48 | 49 | /* Constants for directory routines */ 50 | #define DIRLINES 28 /* # of lines per page */ 51 | #define SORTCOLS 4 /* # of columns of sorted entries */ 52 | #define UNSORTCOLS 5 /* # of columns of unsorted entries */ 53 | 54 | /* Locations for file transfer box */ 55 | #define RPTPOS 42 /* Where the status goes */ 56 | #define LC RPTPOS-23 57 | #define TR 2 58 | #define HT 12 59 | #define WD 41 60 | #define RC LC+WD-1 61 | #define BR TR+HT-1 62 | #define HORIZ '\xC4' 63 | #define VERT '\xB3' 64 | #define UL '\xDA' 65 | #define UR '\xBF' 66 | #define LL '\xC0' 67 | #define LR '\xD9' 68 | 69 | /***************** line numbers for report function *************************/ 70 | 71 | #define PROTOCOL 3 72 | #define PATHNAME 4 73 | #define FILESIZE 5 74 | #define BLKCHECK 6 75 | #define SENDTIME 7 76 | #define KBYTES 8 77 | #define BLOCKS 9 78 | #define FBLOCKS 10 79 | #define ERRORS 11 80 | #define MESSAGE 12 81 | 82 | 83 | #define BUFSTART 16384 /* 16k text buffer starting size */ 84 | #define OK 0 85 | #define NOT_OK (-1) 86 | #define NERROR (-1) 87 | #define ERROR 0 88 | #define KEYHIT 0 89 | #define MAXFILES 255 /* max number of expanded files */ 90 | #define FNSIZE 17 /* filename: 1(A)+3(15:)+8+1+3+null */ 91 | #define BUFIOT 0 /* error return on buffered fopen */ 92 | #define UBIOT -1 /* unbuffered open */ 93 | 94 | 95 | /**************************************************************************/ 96 | /* */ 97 | /* Miscellaneous ASCII characters. */ 98 | /* */ 99 | /**************************************************************************/ 100 | 101 | #define NUL 0 102 | #define SOH 1 103 | #define STX 2 104 | #define CTRLC 3 105 | #define EOT 4 106 | #define CTRLE 5 107 | #define ENQ 5 108 | #define ACK 6 109 | #define BELL 7 110 | #define BS 8 111 | #define LF 10 112 | #define CTRLK 11 113 | #define CR 13 114 | #define CTRLQ 17 /* xon */ 115 | #define XON ('q'&037) 116 | #define CTRLS 19 /* xoff */ 117 | #define XOFF ('s'&037) 118 | #define NAK 21 119 | #define CAN ('X'&037) 120 | #define CTRLX 24 121 | #define CPMEOF 26 122 | #define CTRLZ 26 /*end of text-file character*/ 123 | #define ESC 27 124 | #define DEL 127 125 | 126 | /******************* constants used in file transfer **********************/ 127 | 128 | /* Ward Christensen / CP/M parameters - Don't change these! */ 129 | 130 | #define TIMEOUT -2 131 | #define RCDO (-3) 132 | #define ERRORMAX 5 133 | #define RETRYMAX 10 134 | #define WCEOT (-10) 135 | #define SECSIZ 128 /* cp/m's Magic Number record size */ 136 | #define PATHLEN 257 /* ready for 4.2 bsd ? */ 137 | #define KSIZE 1024 /* record size with k option */ 138 | #define WANTCRC 'C' 139 | #define ORIGIN 0x0100 /*starting point for cp/m programs*/ 140 | #define COMPSIZ 35 /*cpm bdos compute file size command*/ 141 | 142 | 143 | #define CPMBUF 0x80 /*address of cpm file buffer*/ 144 | #define DONE 0xff /*flag for no more entries*/ 145 | #define RET '!' /*symbol for CR string terminator */ 146 | #define WAITASEC '~' /* one second delay */ 147 | #define BIOSADDR 1 /*ptr to base of bios + 3*/ 148 | #define LISTST 42 /*index to list status routine*/ 149 | #define ENABLE 0xfb /*code for EI*/ 150 | #define RTN 0xc9 /*code for RET*/ 151 | #define JUMP 0xc3 /*code for JMP*/ 152 | 153 | /* BIOS entry functions */ 154 | #define BIOS_CONIN 3 /* console input */ 155 | #define BIOS_CONOUT 4 /* console output */ 156 | 157 | /************************ configuration variables **********************************/ 158 | 159 | EXTERN int BFlag 160 | #ifdef MAIN 161 | = FALSE 162 | #endif 163 | ; 164 | EXTERN int PFlag 165 | #ifdef MAIN 166 | = FALSE 167 | #endif 168 | ; 169 | EXTERN int FDx 170 | #ifdef MAIN 171 | = TRUE 172 | #endif 173 | ; 174 | EXTERN int RemEcho 175 | #ifdef MAIN 176 | = FALSE 177 | #endif 178 | ; 179 | EXTERN int Online 180 | #ifdef MAIN 181 | = FALSE 182 | #endif 183 | ; 184 | EXTERN int Filter 185 | #ifdef MAIN 186 | = FALSE 187 | #endif 188 | ; 189 | EXTERN int ParityMask 190 | #ifdef MAIN 191 | = FALSE 192 | #endif 193 | ; 194 | EXTERN char Msgfile[20] 195 | #ifdef MAIN 196 | = "ZMP.MSG" 197 | #endif 198 | ; 199 | EXTERN char Phonefile[20] 200 | #ifdef MAIN 201 | = "ZMP.FON" 202 | #endif 203 | ; 204 | EXTERN char Logfile[20] 205 | #ifdef MAIN 206 | = "ZMP.LOG" 207 | #endif 208 | ; 209 | EXTERN char Cfgfile[20] 210 | #ifdef MAIN 211 | = "ZMP.CFG" 212 | #endif 213 | ; 214 | EXTERN char Configovly[9] 215 | #ifdef MAIN 216 | = "ZMCONFIG" 217 | #endif 218 | ; 219 | EXTERN char Initovly[9] 220 | #ifdef MAIN 221 | = "ZMINIT" 222 | #endif 223 | ; 224 | EXTERN char Termovly[9] 225 | #ifdef MAIN 226 | = "ZMTERM" 227 | #endif 228 | ; 229 | EXTERN char Xferovly[9] 230 | #ifdef MAIN 231 | = "ZMXFER" 232 | #endif 233 | ; 234 | EXTERN char KbMacro[10][22] 235 | #ifdef MAIN 236 | = { 237 | "Macro Key 0!", 238 | "Macro Key 1!", 239 | "Macro Key 2!", 240 | "Macro Key 3!", 241 | "Macro Key 4!", 242 | "Macro Key 5!", 243 | "Macro Key 6!", 244 | "Macro Key 7!", 245 | "Macro Key 8!", 246 | "Macro Key 9!" 247 | } 248 | #endif 249 | ; 250 | 251 | EXTERN struct modemparms { 252 | char init[41]; 253 | char dialcmd[9]; 254 | char dialsuffix[9]; 255 | char connect[21]; 256 | char busy1[21]; 257 | char busy2[21]; 258 | char busy3[21]; 259 | char busy4[21]; 260 | char hangup[21]; 261 | int timeout; 262 | int pause; 263 | } Modem 264 | #ifdef MAIN 265 | = { 266 | "ATE0V1X4S0=0!", 267 | "ATD", 268 | "!", 269 | "CONNECT", 270 | "BUSY", 271 | "NO CARRIER", 272 | "NO ANSWER", 273 | "ERROR", 274 | "~+++~ATH0!", 275 | 40,8 276 | } 277 | #endif 278 | ; 279 | 280 | EXTERN struct lineparms { 281 | int baudindex; 282 | char parity; 283 | int databits; 284 | int stopbits; 285 | } Line 286 | #ifdef MAIN 287 | = { DFLTINDEX, 'N', 8, 1 } 288 | #endif 289 | ; 290 | EXTERN int Pbufsiz 291 | #ifdef MAIN 292 | = PBUFSIZ 293 | #endif 294 | ; 295 | EXTERN int Maxdrive 296 | #ifdef MAIN 297 | = 'P' 298 | #endif 299 | ; 300 | EXTERN struct phonebook { 301 | char name[19]; 302 | char number[19]; 303 | int pbaudindex; 304 | char pparity; 305 | int pdatabits; 306 | int pstopbits; 307 | int echo; 308 | } *Book; 309 | 310 | EXTERN char *Prtbuf; 311 | EXTERN unsigned Buftop; 312 | EXTERN char *Prthead; 313 | EXTERN char *Prttail; 314 | EXTERN char *Prttop; 315 | EXTERN char *Prtbottom; 316 | EXTERN int Inhost 317 | #ifdef MAIN 318 | = FALSE 319 | #endif 320 | ; 321 | #ifdef INIT 322 | char Version[41] 323 | = "Version 1.5+/- -- 24 July 2020" /* version number for ZMP */ 324 | = "Version 1.5+/- -- 15 Aug 2023 " /* version number for ZMP */ 325 | /* ^_____________________________________^ Maximum length! */ 326 | #endif 327 | ; 328 | EXTERN char Lastlog[20]; 329 | 330 | EXTERN int Dialing; 331 | EXTERN int Lastkey; 332 | 333 | EXTERN int Chardelay 334 | #ifdef MAIN 335 | = 0 336 | #endif 337 | ; 338 | EXTERN int Linedelay 339 | #ifdef MAIN 340 | = 0 341 | #endif 342 | ; 343 | EXTERN int FirsTerm /* Flag -- first time terminal overlay runs */ 344 | #ifdef MAIN 345 | = TRUE 346 | #endif 347 | ; 348 | 349 | EXTERN int Invokdrive, Currdrive, Invokuser, Curruser; 350 | EXTERN int Overdrive, Overuser, Userid; 351 | 352 | EXTERN char *Userover; 353 | 354 | EXTERN struct settings { 355 | int cbaudindex; 356 | char cparity; 357 | int cdatabits; 358 | int cstopbits; 359 | } Current; 360 | 361 | EXTERN unsigned Baudtable[14] 362 | #ifdef MAIN 363 | = { 11,30,45,60,71,120,240,480,960,1920,3840,5760,7680 } 364 | #endif 365 | ; 366 | EXTERN int QuitFlag /* Operator abort */ 367 | #ifdef MAIN 368 | = FALSE 369 | #endif 370 | ; 371 | EXTERN int StopFlag /* abort/stop from remote end */ 372 | #ifdef MAIN 373 | = FALSE 374 | #endif 375 | ; 376 | EXTERN int Crcflag 377 | #ifdef MAIN 378 | = TRUE 379 | #endif 380 | ; 381 | EXTERN int XonXoff 382 | #ifdef MAIN 383 | = FALSE 384 | #endif 385 | ; 386 | EXTERN int XonXoffOk 387 | #ifdef MAIN 388 | = FALSE 389 | #endif 390 | ; 391 | EXTERN int Sending /* file transfer direction */ 392 | #ifdef MAIN 393 | = FALSE 394 | #endif 395 | ; 396 | EXTERN int Zmodem 397 | #ifdef MAIN 398 | = FALSE 399 | #endif 400 | ; 401 | EXTERN int Nozmodem 402 | #ifdef MAIN 403 | = FALSE 404 | #endif 405 | ; 406 | EXTERN int Blklen 407 | #ifdef MAIN 408 | = SECSIZ 409 | #endif 410 | ; 411 | EXTERN int Xmodem 412 | #ifdef MAIN 413 | = FALSE 414 | #endif 415 | ; 416 | EXTERN int Zrwindow /* RX window size (controls garbage count) */ 417 | #ifdef MAIN 418 | = 1400 419 | #endif 420 | ; 421 | EXTERN unsigned Bufsize 422 | #ifdef MAIN 423 | = BUFSTART 424 | #endif 425 | ; 426 | 427 | EXTERN char Pathname[128]; 428 | EXTERN char Buf[128]; /* general purpose buffer */ 429 | EXTERN char *MainBuffer; 430 | EXTERN unsigned TxtPtr 431 | #ifdef MAIN 432 | = 0 433 | #endif 434 | ; 435 | EXTERN int Stopped 436 | #ifdef MAIN 437 | = FALSE 438 | #endif 439 | ; 440 | EXTERN char *Mspeed 441 | #ifdef MAIN 442 | = (char *) 0x3c 443 | #endif 444 | ; 445 | EXTERN char *Wheel 446 | #ifdef MAIN 447 | = (char *) 0x3e 448 | #endif 449 | ; 450 | EXTERN int Wantfcs32 451 | #ifdef MAIN 452 | = TRUE 453 | #endif 454 | ; 455 | 456 | EXTERN int ZsDos 457 | #ifdef MAIN 458 | = TRUE 459 | #endif 460 | ; 461 | 462 | EXTERN unsigned long FileModTime; 463 | 464 | struct stat { 465 | char fname[9]; 466 | char fext[4]; 467 | unsigned long modtime; 468 | int records; 469 | }; 470 | 471 | struct direntry { 472 | char userno; 473 | char flname[8]; 474 | char ftype[3]; 475 | char fextent; 476 | char reserved[2]; 477 | char record; 478 | char map[16]; 479 | }; 480 | 481 | struct sortentry { 482 | unsigned char user; /* user area */ 483 | char name[8]; /* filename */ 484 | char type[3]; /* filetype */ 485 | char ex; /* low byte of extent (0 - 31) */ 486 | char s1; /* unused */ 487 | char s2; /* count of extents over 31 */ 488 | unsigned char rc; /* record count */ 489 | }; 490 | 491 | EXTERN struct fcb Thefcb; 492 | 493 | struct dpb { 494 | unsigned spt; 495 | char bsh; 496 | char blm; 497 | char exm; 498 | unsigned dsm; 499 | unsigned drm; 500 | char al0; 501 | char al1; 502 | unsigned cks; 503 | unsigned off; 504 | }; 505 | 506 | EXTERN char **Pathlist; 507 | 508 | /******************************* end of zmp.h ******************************/ 509 |  510 | -------------------------------------------------------------------------------- /src/zmp2.c: -------------------------------------------------------------------------------- 1 | /* MAIN module File #2 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "zmp.h" 8 | 9 | extern char *alloc(int); 10 | extern int mirdy(); 11 | extern int moutrdy(); 12 | extern int mchin(); 13 | extern int mrd(); 14 | extern int getch(); 15 | 16 | int mread(char *buffer, int count, int timeout); 17 | unsigned mcharinp(); 18 | static void clrbox(); 19 | 20 | int roundup(dividend,divisor) 21 | int dividend, divisor; 22 | { 23 | return (dividend/divisor + ((dividend%divisor) ? 1 : 0)); 24 | } 25 | 26 | int getfirst(aname) /* ambiguous file name */ 27 | char *aname; 28 | { 29 | bdos(CPMSDMA,CPMBUF); /* set dma address */ 30 | setfcb(&Thefcb,aname); 31 | return bdos(CPMFFST,&Thefcb) & 0xff; 32 | } 33 | 34 | int getnext() 35 | { 36 | bdos(CPMSDMA,CPMBUF); /* set dma address */ 37 | return bdos(CPMFNXT,NULL) & 0xff; 38 | } 39 | 40 | /* command: expand wild cards in the command line. (7/25/83) 41 | * usage: command(&argc, &argv) modifies argc and argv as necessary 42 | * uses sbrk to create the new arg list 43 | * NOTE: requires fcbinit() and bdos() from file stdlib.c. When used 44 | * with a linker and stdlib.rel, remove the #include stdlib.c. 45 | * 46 | * Written by Dr. Jim Gillogly; Modified for CP/M by Walt Bilofsky. 47 | * Modified by HM to just get ambiguous fn for zmodem, ymodem. 48 | */ 49 | 50 | int COMnf,COMc; 51 | char **COMfn; 52 | char **COMv; 53 | char *COMarg,*COMs; 54 | static expand(); 55 | 56 | void command(argcp, argvp) 57 | int *argcp; 58 | char ***argvp; 59 | { 60 | char *p, c; 61 | char *f_alloc[MAXFILES]; 62 | 63 | COMfn = f_alloc; 64 | COMc = *argcp; 65 | COMv = *argvp; 66 | COMnf = 0; 67 | for (COMarg = *COMv; COMc--; COMarg = *++COMv) { 68 | 69 | #ifdef DEBUG 70 | printf("\nDoing %s",COMarg); 71 | #endif 72 | 73 | for (COMs = COMarg; *COMs; COMs++) { 74 | if (*COMs == '?' || *COMs == '*') { 75 | if (!expand()) { /* Too many */ 76 | *argcp = 0; 77 | return; 78 | } 79 | goto contn; /* expand each name at most once */ 80 | } 81 | } 82 | COMfn[COMnf] = alloc(FNSIZE); 83 | p = COMarg; 84 | while (c = *p) { /* Convert to lower case */ 85 | *p++ = tolower(c); 86 | } 87 | strcpy(COMfn[COMnf++],COMarg); /* no expansion */ 88 | contn:; 89 | } 90 | *argcp = COMnf; 91 | COMfn[COMnf++] = NULL; 92 | COMv = *argvp = (char **)alloc(2 * COMnf); 93 | while (COMnf--) { 94 | COMv[COMnf] = COMfn[COMnf]; 95 | } 96 | } 97 | 98 | int static expand() /* Returns FALSE if error */ 99 | { 100 | struct fcb searchfcb; 101 | static char *p,*q,*r,c; 102 | static int i,flg,olduser; 103 | 104 | #ifdef DEBUG 105 | printf("\nExpanding %s",COMarg); 106 | #endif 107 | olduser = getuid(); /* save original user area */ 108 | setfcb(&searchfcb,COMarg); 109 | setuid(searchfcb.uid); /* go to specified user area */ 110 | flg = CPMFFST; 111 | bdos(CPMSDMA,0x80); /* Make sure DMA address OK */ 112 | while (((i = bdos(flg,&searchfcb)) & 0xff) != 0xff) { 113 | COMfn[COMnf++] = q = alloc(FNSIZE); 114 | if (COMnf >= MAXFILES-1) { 115 | for (p = "Too many file names.\n"; putchar(*p++); ); { 116 | setuid(olduser); 117 | return FALSE; 118 | } 119 | } 120 | p = (char *)(0x81 + i * 32); /* Where to find dir. record */ 121 | /* transfer du: first */ 122 | if (strchr(COMarg,':') && COMarg[0] != '?') { 123 | r = COMarg; 124 | do { 125 | *q++ = c = *r++; 126 | } while (c != ':'); 127 | } 128 | /* Now transfer filename */ 129 | for (i = 12; --i; ) { 130 | if (i == 3) { 131 | *q++ = '.'; 132 | } 133 | *q = *p++ & 0x7F; 134 | *q = tolower(*q); 135 | if (*q != ' ') { 136 | ++q; 137 | } 138 | } 139 | *q = 0; 140 | flg = CPMFNXT; 141 | } 142 | setuid(olduser); 143 | return TRUE; 144 | } 145 | 146 | int ctr(p) 147 | char *p; 148 | { 149 | if( strlen(p) >= 80 ) { 150 | return 0; 151 | } 152 | return (80 - strlen(p))/2; 153 | } 154 | 155 | int opabort() 156 | { 157 | Lastkey = getch() & 0xff; 158 | if (Lastkey == ESC) { 159 | flush(); 160 | if (!Inhost && !Dialing) { 161 | report(MESSAGE,"Operator abort"); 162 | } 163 | QuitFlag = TRUE; 164 | } 165 | return QuitFlag; 166 | } 167 | 168 | /* 169 | * readock(timeout, count) reads character(s) from modem 170 | * (1 <= count <= 3) 171 | * it attempts to read count characters. If it gets more than one, 172 | * it is an error unless all are CAN 173 | * (otherwise, only normal response is ACK, CAN, or C) 174 | * 175 | * timeout is in tenths of seconds 176 | */ 177 | 178 | int readock(timeout, count) 179 | int timeout, count; 180 | { 181 | int c; 182 | char byt[5]; 183 | 184 | c = mread(byt,count,timeout); 185 | if (c < 1) { 186 | return TIMEOUT; 187 | } 188 | if (c == 1) { 189 | return byt[0] & 0xFF; 190 | } else { 191 | while (c) { 192 | if (byt[--c] != CAN) { 193 | return NERROR; 194 | } 195 | } 196 | return CAN; 197 | } 198 | } 199 | 200 | /* 201 | * readline(n): reads 1 character from modem in n/10 seconds 202 | */ 203 | int readline(n) 204 | int n; 205 | { 206 | return readock(n,1); 207 | } 208 | 209 | void putlabel(string) 210 | char string[]; 211 | { 212 | cls(); 213 | locate(0,ctr(string) - 1); /* Centre on top line */ 214 | stndout(); /* Inverse video */ 215 | printf(" %s \n\n",string); /* Print the string */ 216 | stndend(); /* Inverse off */ 217 | } 218 | 219 | void killlabel() /*disable 25th line*/ 220 | { 221 | cls(); /* just clear screen */ 222 | } 223 | 224 | int mgetchar(seconds) /* allows input from modem or operator */ 225 | int seconds; 226 | { 227 | static int c, tenths; 228 | 229 | Lastkey = 0; 230 | tenths = seconds * 10; 231 | if ((c=readline(tenths)) != TIMEOUT) { 232 | return c & 0xff; 233 | } else if (Lastkey) { 234 | return Lastkey; 235 | } 236 | return TIMEOUT; 237 | } 238 | 239 | void box() /* put box on screen for file transfer */ 240 | { 241 | register int i; 242 | static char *headings[] = { 243 | "", 244 | "Protocol:", 245 | "File Name:", 246 | "File Size:", 247 | "Block Check:", 248 | "Transfer Time:", 249 | "Bytes Transferred:", 250 | "Blocks Transferred:", 251 | "Sectors in File:", 252 | "Error Count:", 253 | "Last Message: NONE" 254 | }; 255 | static int start[] = { 256 | 0, 257 | 13+LC, 258 | 12+LC, 259 | 12+LC, 260 | 10+LC, 261 | 8+LC, 262 | 4+LC, 263 | 3+LC, 264 | 6+LC, 265 | 10+LC, 266 | 9+LC 267 | }; 268 | 269 | locate(TR,LC); 270 | bios(BIOS_CONOUT,UL); 271 | for (i = 1; i < WD-1; i++) { 272 | bios(BIOS_CONOUT,HORIZ); 273 | } 274 | bios(BIOS_CONOUT,UR); 275 | locate(BR,LC); 276 | bios(BIOS_CONOUT,LL); 277 | for (i = 1; i < WD-1; i++) { 278 | bios(BIOS_CONOUT,HORIZ); 279 | } 280 | bios(BIOS_CONOUT,LR); 281 | for (i = 1; i < HT-1; i++) { 282 | locate(TR+i,LC); 283 | bios(BIOS_CONOUT,VERT); 284 | locate(TR+i,RC); 285 | bios(BIOS_CONOUT,VERT); 286 | } 287 | clrbox(); 288 | for (i=1; i<11; i++) { 289 | locate(TR+i,start[i]); 290 | printf(headings[i]); 291 | } 292 | } 293 | 294 | static void clrbox() 295 | { 296 | register int i; 297 | 298 | for (i=TR+1; i < BR; i++) { 299 | locate(i,LC+1); 300 | printf(" "); 301 | } 302 | } 303 | 304 | int mread(buffer, count, timeout) /* time in tenths of secs */ 305 | char *buffer; 306 | int count, timeout; 307 | { 308 | int i, c; 309 | 310 | i = 0; 311 | while (!(c = mrd()) && (timeout--) && !opabort()); 312 | if (c) { 313 | buffer[i++] = mcharinp(); 314 | } 315 | return i; 316 | } 317 | 318 | unsigned mcharinp() 319 | { 320 | unsigned c; 321 | 322 | c = mchin(); 323 | if (Stopped) { 324 | mchout(CTRLQ); 325 | Stopped = FALSE; 326 | } 327 | return c; 328 | } 329 | 330 | void mcharout(c) 331 | char c; 332 | { 333 | while (!moutrdy()) { 334 | opabort(); /* Test for operator abort while we wait */ 335 | } 336 | mchout(c); /* Then send it */ 337 | } 338 | 339 | int minprdy() 340 | { 341 | return mirdy() || Stopped; 342 | } 343 | 344 | /* End of MAIN module */ 345 |  -------------------------------------------------------------------------------- /src/zmp3.c: -------------------------------------------------------------------------------- 1 | /* MAIN module File #3 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include "zmp.h" 7 | 8 | static int bin2bcd(bin) 9 | int bin; 10 | { 11 | return ((bin / 10) << 4) | (bin % 10); 12 | } 13 | 14 | static int bcd2bin(bcd) 15 | uchar bcd; 16 | { 17 | return 10*(bcd>>4)+(bcd&0x0F); 18 | } 19 | 20 | void setmodtime() 21 | { 22 | struct fcb fc; 23 | short luid; 24 | struct tm *tp; 25 | 26 | if (ZsDos && FileModTime && !setfcb(&fc, Pathname)) { 27 | tp = localtime(&FileModTime); 28 | Buf[0] = Buf[5] = Buf[10] = bin2bcd(tp->tm_year % 100); 29 | Buf[1] = Buf[6] = Buf[11] = bin2bcd(tp->tm_mon+1); 30 | Buf[2] = Buf[7] = Buf[12] = bin2bcd(tp->tm_mday); 31 | Buf[3] = Buf[8] = Buf[13] = bin2bcd(tp->tm_hour); 32 | Buf[4] = Buf[9] = Buf[14] = bin2bcd(tp->tm_min); 33 | bdos(CPMSDMA,Buf); 34 | luid = getuid(); 35 | setuid(fc.uid); 36 | bdos(CPMSSTP, &fc); 37 | setuid(luid); 38 | } 39 | } 40 | 41 | static time_t getmodtime(fcbp) 42 | struct fcb *fcbp; 43 | { 44 | int olduser; 45 | unsigned char *p; 46 | struct tm ftm; 47 | time_t tt = 0; 48 | 49 | if (ZsDos) { 50 | bdos(CPMSDMA,CPMBUF); /* set dma address */ 51 | olduser = getuid(); 52 | setuid(fcbp->uid); 53 | bdos(CPMGSTP, fcbp); 54 | p = (unsigned char *)(CPMBUF+10); 55 | ftm.tm_year = bcd2bin(*p); 56 | if (ftm.tm_year < 78) { 57 | ftm.tm_year += 100; 58 | } 59 | ++p; 60 | ftm.tm_mon = bcd2bin(*p) - 1; 61 | ++p; 62 | ftm.tm_mday = bcd2bin(*p); 63 | ++p; 64 | ftm.tm_hour = bcd2bin(*p); 65 | ++p; 66 | ftm.tm_min = bcd2bin(*p); 67 | ftm.tm_sec = 0; 68 | tt = mktime(&ftm); 69 | setuid(olduser); 70 | } 71 | return tt; 72 | } 73 | 74 | static unsigned filelength(fcbp) 75 | struct fcb *fcbp; 76 | { 77 | int olduser; 78 | 79 | bdos(CPMSDMA,CPMBUF); /* set dma address */ 80 | olduser = getuid(); /* save this user number */ 81 | setuid(fcbp->uid); /* go to file's user no. */ 82 | bdos(CPMCFS,fcbp); /* compute file size */ 83 | setuid(olduser); /* restore original */ 84 | return (fcbp->ranrec[1]<<8)|fcbp->ranrec[0]; 85 | } 86 | 87 | void fstat(fname,status) 88 | char *fname; 89 | struct stat *status; 90 | { 91 | setfcb(&Thefcb,fname); 92 | status->modtime = getmodtime(&Thefcb); 93 | status->records = filelength(&Thefcb); 94 | getfirst(fname); 95 | setfcb(&Thefcb,"????????.???"); 96 | } 97 | 98 | /* End of MAIN module */ 99 |  -------------------------------------------------------------------------------- /src/zmterm.c: -------------------------------------------------------------------------------- 1 | /* TERM module File #1 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "zmp.h" 9 | 10 | #define autolen 6 /* length of ZRQINIT required for auto rx */ 11 | 12 | extern char *alloc(int); 13 | extern int allocerror(void *); 14 | extern int getch(); 15 | extern int help(); 16 | extern int minprdy(); 17 | extern int mcharinp(); 18 | extern int dio(); 19 | extern int dial(); 20 | extern int screenpr(); 21 | 22 | static void prtchr(char); 23 | static void tobuffer(int); 24 | static void prompt(short); 25 | static void toprinter(int); 26 | static void toggleprt(); 27 | static int getprtbuf(); 28 | static void doexit(); 29 | static int prtservice(); 30 | static int pready(); 31 | static void adjustprthead(); 32 | 33 | ovmain() 34 | { 35 | short mdmdata, dolabel, keycount, keypoint, keywait; 36 | short lastkey = '\0', fkey, autopos, escwait; 37 | char keybuf[25]; 38 | static char autoseq[] = { '*','*',CTRLX,'B','0','0' }; 39 | char kbdata; 40 | char literal; 41 | 42 | if (FirsTerm) { 43 | locate(0,0); /* print header if first time*/ 44 | prompt(FALSE); /* but don't clear screen */ 45 | locate(15,0); /* then put cursor near bottom */ 46 | printf("Ready. \n"); /* overwrite 'wait' */ 47 | FirsTerm = FALSE; /* don't come here again */ 48 | } else { 49 | prompt(TRUE); 50 | } 51 | startcapture(); 52 | autopos = keycount = 0; /* no remote xfer, no keys in buffer */ 53 | keywait = 0; 54 | Zmodem = FALSE; /* ensure we don't auto zmodem */ 55 | purgeline(); /* get rid of any junk */ 56 | literal = FALSE; 57 | 58 | /* Main loop: */ 59 | for (;;) { 60 | kbdata = '\0'; 61 | if (keywait) { 62 | --keywait; 63 | mswait(1); 64 | } else if (keycount) { /* get any buffered keys */ 65 | kbdata = keybuf[keypoint++]; 66 | keycount--; 67 | keywait = 25; 68 | if (kbdata == '\\') { 69 | if (literal) { 70 | literal = FALSE; 71 | } else { 72 | kbdata = '\0'; 73 | literal = TRUE; 74 | } 75 | } else if (kbdata == RET ) { /* Translate ! to CR */ 76 | if (!literal) { 77 | kbdata = CR; 78 | } 79 | literal = FALSE; 80 | } else if (kbdata == WAITASEC) { 81 | if (!literal) { 82 | keywait = 1000; /* handle pause */ 83 | kbdata = '\0'; /* that's it for this loop */ 84 | } 85 | literal = FALSE; 86 | } 87 | } /* end of function keys */ 88 | if (!kbdata && !keycount) { 89 | kbdata = getch(); /* if none, any at keyboard */ 90 | if (kbdata == ESC) { /* if another key follows an ESC */ 91 | escwait = 5; /* within 5ms, it's a keyboard */ 92 | do { /* cursor or function key - just */ 93 | kbdata = getch();/* send it */ 94 | if (!kbdata) { 95 | mswait(1); 96 | } 97 | } while (!kbdata && --escwait > 0); 98 | if (kbdata) { /* keyboard cursor/function key */ 99 | mcharout(ESC); /* send ESC right now and let */ 100 | if (!FDx) { /* ZMP see next char in sequence*/ 101 | prtchr(ESC); 102 | } 103 | } else { 104 | kbdata = ESC; /* if no next char, normal ZMP */ 105 | } /* ESC processing */ 106 | } 107 | } 108 | if (kbdata) { 109 | if (lastkey == ESC) { 110 | fkey = toupper(kbdata); 111 | /* allow ESC ESC without complications */ 112 | lastkey = (kbdata == ESC) ? '\0' : kbdata; 113 | dolabel = TRUE; 114 | if (fkey == HELP) { 115 | keybuf[0] = help(); 116 | if (keybuf[0]) { 117 | lastkey = ESC; 118 | keycount = 1; 119 | keypoint = 0; 120 | dolabel = FALSE; 121 | } 122 | } else if (fkey==RECEIVE || fkey==SEND || fkey==CONFIG) { 123 | keep(Lastlog,FALSE); 124 | return fkey; 125 | } else if (fkey==CAPTURE) { 126 | capturetog(Logfile); 127 | dolabel = FALSE; 128 | } else if (fkey==DIR) { 129 | killlabel(); 130 | keep(Lastlog,FALSE); 131 | directory(); 132 | startcapture(); 133 | dolabel = FALSE; 134 | } else if (fkey==PRTSCRN) { 135 | screenpr(); 136 | dolabel = FALSE; 137 | } else if (fkey==HANGUP) { 138 | hangup(); 139 | dolabel = FALSE; 140 | } else if (fkey==COMMAND) { 141 | docmd(); 142 | } else if (fkey==DIAL) { 143 | keep(Lastlog,FALSE); 144 | dial(); 145 | dolabel = FALSE; 146 | purgeline(); 147 | startcapture(); 148 | } else if (fkey==TOGPRT) { 149 | toggleprt(); 150 | dolabel = FALSE; 151 | } else if (fkey==DISK) { 152 | diskstuff(); 153 | } else if (fkey==QUIT) { 154 | doexit(); 155 | } else if (fkey==CLRSCR) { 156 | cls(); 157 | } else if (fkey==BRK) { 158 | sendbrk(); 159 | printf("\nBreak sent.\n"); 160 | dolabel = FALSE; 161 | } else if (fkey==DISPKEYS) { 162 | keydisp(); 163 | dolabel = FALSE; 164 | } else { 165 | dolabel = FALSE; 166 | if (fkey>='0' && fkey<='9') { 167 | strcpy(keybuf,KbMacro[fkey-'0']); 168 | keycount = strlen(keybuf); 169 | keypoint = 0; 170 | } else { 171 | mcharout(kbdata); /* send it if not anything else */ 172 | } 173 | } 174 | 175 | if (dolabel) { 176 | prompt(TRUE); /* print header */ 177 | } 178 | /* end of if lastkey == ESC */ 179 | } else if ((lastkey = kbdata) != ESC) { 180 | mcharout(kbdata); /* Not a function key */ 181 | ilfloop: 182 | if (!FDx) { 183 | prtchr(kbdata); 184 | if (kbdata == CR) { 185 | kbdata = LF; 186 | if (RemEcho) { 187 | mcharout(kbdata); 188 | } 189 | goto ilfloop; 190 | } 191 | } 192 | } 193 | } /* end of if char at kbd */ 194 | 195 | if (minprdy()) { 196 | mdmdata = mcharinp(); /* Character at modem */ 197 | if (mdmdata == autoseq[autopos++]) { /* ZRQINIT? */ 198 | if (autopos == autolen) { 199 | printf("\nZmodem receive.\n"); 200 | Zmodem = TRUE; /* yes, do auto.. */ 201 | return RECEIVE; /* ..zmodem receive */ 202 | } 203 | } else { 204 | /* no, reset ZRQINIT sequence test */ 205 | autopos = (mdmdata == '*') ? 1 : 0; 206 | } 207 | if (ParityMask) { /* if flag on, */ 208 | mdmdata &= 0x7f; /* remove parity */ 209 | } 210 | if (Filter && (mdmdata > '\r') && (mdmdata < ' ')) { 211 | goto endloop; /* filter control chars */ 212 | } 213 | olfloop: 214 | prtchr(mdmdata); /* print the character */ 215 | tobuffer(mdmdata); 216 | toprinter(mdmdata); 217 | if (RemEcho) { 218 | mcharout(mdmdata); 219 | if (mdmdata == CR) { 220 | mdmdata = LF; 221 | goto olfloop; 222 | } 223 | } 224 | } 225 | endloop: 226 | prtservice(); /* service printer at the end of each loop */ 227 | } /* end of while */ 228 | } /* end of main */ 229 | 230 | 231 | /* print character, handling tabs (can't use bdos 2 as it reacts to ctl-s) */ 232 | static void prtchr(c) 233 | char c; 234 | { 235 | bios(BIOS_CONOUT,c); 236 | } 237 | 238 | static void tobuffer(c) 239 | int c; 240 | { 241 | if (BFlag && c) { 242 | MainBuffer[TxtPtr++] = (char)c; 243 | if (TxtPtr > Buftop) { 244 | keep(Lastlog,TRUE); /* must be true since remote */ 245 | startcapture(); /* is probably still going */ 246 | } 247 | } 248 | } 249 | 250 | /* Print message at top of page. Clear screen first if clear set */ 251 | static void prompt(clear) 252 | short clear; 253 | { 254 | time_t tt; 255 | struct tm *ptm; 256 | char ampm; 257 | int hh; 258 | 259 | if (clear) { 260 | cls(); 261 | } 262 | printf("\rTerminal Mode: ESC H for help.\t\t"); 263 | printf( 264 | "Drive %c%d: %u0 baud", 265 | Currdrive,Curruser, 266 | Baudtable[Current.cbaudindex]); 267 | if( ZsDos ) { 268 | tt = time(NULL); 269 | ptm = gmtime(&tt); 270 | hh = ptm->tm_hour; 271 | if (hh < 12) { 272 | ampm = 'A'; 273 | } else { 274 | ampm = 'P'; 275 | hh -= 12; 276 | } 277 | if (!hh) { 278 | hh = 12; 279 | } 280 | printf("\t\t%2d:%02d%cM",hh,ptm->tm_min,ampm); 281 | } 282 | putchar('\n'); 283 | } 284 | 285 | static void toprinter(i) 286 | int i; 287 | { 288 | char c; 289 | 290 | c = (char) i; 291 | if (PFlag && (c != '\f')) { /* don't print form feeds */ 292 | *Prthead++ = c; 293 | adjustprthead(); 294 | } 295 | } 296 | 297 | static void toggleprt() 298 | { 299 | PFlag = !PFlag; 300 | if (PFlag) { 301 | if (getprtbuf() != OK) { 302 | PFlag = FALSE; 303 | } else { 304 | printf("\nPrinter ON\n"); 305 | } 306 | } else { 307 | while (prtservice()) 308 | ; /* Empty the buffer */ 309 | bdos(CPMWLST,'\r'); /* do final cr/lf */ 310 | bdos(CPMWLST,'\n'); 311 | free(Prtbuf); 312 | printf("\nPrinter OFF\n"); 313 | } 314 | } 315 | 316 | static int getprtbuf() 317 | { 318 | keep(Lastlog,TRUE); /* need to steal some of the buffer */ 319 | Prtbuf = alloc(Pbufsiz); 320 | if (allocerror(Prtbuf)) { 321 | return NERROR; 322 | } 323 | Prthead = Prttail = Prtbottom = Prtbuf; 324 | Prttop = Prtbuf + Pbufsiz - 1; 325 | startcapture(); 326 | 327 | #ifdef DEBUG 328 | printf("\nPrtbuf = %x\n",Prtbuf); 329 | #endif 330 | 331 | return OK; 332 | } 333 | 334 | /* Quit. */ 335 | static void doexit() 336 | { 337 | char c; 338 | 339 | killlabel(); 340 | putlabel("Are you SURE you want to exit ZMP? (Y/N) "); 341 | c = dio(); 342 | if (toupper(c) == 'N') { 343 | return; 344 | } 345 | keep(Lastlog,FALSE); 346 | reset(Invokdrive,Invokuser); 347 | deinitve(); /*restore interrupt vector*/ 348 | cls(); 349 | userout(); /* user-defined exit routine */ 350 | exit(0); /* and quit */ 351 | 352 | } 353 | 354 | static int prtservice() /*printer service routine*/ 355 | { 356 | if (PFlag) { 357 | if (pready()) { 358 | if (Prthead != Prttail) { 359 | bdos(CPMWLST,*Prttail++); /* write list byte */ 360 | if (Prttail > Prttop) { 361 | Prttail = Prtbottom; 362 | } 363 | } 364 | return (Prthead != Prttail); /* Return true if buffer full */ 365 | } 366 | } 367 | return FALSE; 368 | } 369 | 370 | static int pready() /*get printer status using bios call*/ 371 | { 372 | return (bios(14 + 1)); 373 | } 374 | 375 | static void adjustprthead() 376 | { 377 | if (Prthead > Prttop) { 378 | Prthead = Prtbottom; 379 | } 380 | } 381 | 382 | /* End of TERM module File 1 */ 383 |  -------------------------------------------------------------------------------- /src/zmterm.lnk: -------------------------------------------------------------------------------- 1 | -c40d2h -ptext=40d2h,data -ozmterm.ovr -mzmterm.map zmterm.obj \ 2 | zmterm2.obj zmterm3.obj zmterm4.obj main.obj libc.lib 3 |  -------------------------------------------------------------------------------- /src/zmterm3.c: -------------------------------------------------------------------------------- 1 | /* TERM module File 3 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "zmp.h" 8 | 9 | extern int dio(); 10 | extern int getfirst(char *); 11 | extern int getnext(); 12 | extern char *alloc(int); 13 | extern int allocerror(void *); 14 | 15 | int domore(); 16 | void sorted_dir(char *,unsigned); 17 | void unsort_dir(); 18 | void updateace(); 19 | int printsep(short); 20 | int cntbits(char); 21 | 22 | static short Lines, Entries; 23 | 24 | void directory() 25 | { 26 | short factor, cpm3; 27 | long *lp = (long *) CPMBUF; 28 | unsigned i, dtotal, atotal, allen, remaining, bls, dirbufsize; 29 | char *grabmem(), *alloca, *p, *dirbuf; 30 | struct dpb *thedpb; 31 | 32 | cls(); 33 | sprintf(Buf,"Directory for Drive %c%d:",Currdrive,Curruser); 34 | putlabel(Buf); 35 | bdos(CPMSDMA,CPMBUF); /* set dma address */ 36 | cpm3 = (bdoshl(CPMVERS) >= 0x30); /* get cp/m version (BCD) */ 37 | dirbuf = grabmem(&dirbufsize); 38 | if (dirbuf != (char *) MEMORY_FULL) { 39 | sorted_dir(dirbuf,dirbufsize); 40 | } else { /* not enough room */ 41 | unsort_dir(); /* do unsorted directory */ 42 | } 43 | 44 | /* Now print free space on disk */ 45 | if (cpm3) { /* cp/m 3 */ 46 | bdos(CPMGDFS,Currdrive - 'A'); 47 | p = (char *) (CPMBUF + 3); 48 | *p = 0; /* clear hi byte for long */ 49 | remaining = (short) (*lp / 8L); 50 | } else { /* cp/m 2.2 */ 51 | thedpb = (struct dpb *) bdoshl(CPMGDPB); /* fill dpb */ 52 | alloca = (char *) bdoshl(CPMGALL); 53 | bls = 0x0001; 54 | bls <<= thedpb->bsh + 7; 55 | factor = bls/1024; 56 | dtotal = factor * (thedpb->dsm+1); 57 | allen = (thedpb->dsm / 8) + 1; 58 | for (atotal = i = 0; i < allen; i++) { 59 | atotal += cntbits(*(alloca + i)); 60 | } 61 | atotal *= factor; 62 | remaining = dtotal - atotal; 63 | } 64 | if (Lines >= DIRLINES - 1) { 65 | domore(); 66 | } 67 | if (Entries) { 68 | printf("\n\t%d",Entries); 69 | } else { 70 | printf("\n\tNo"); 71 | } 72 | printf(" File(s).\t\t"); 73 | printf("Space remaining on %c: %dk\n",Currdrive,remaining); 74 | } 75 | 76 | /* Do sorted directory with filesizes */ 77 | void sorted_dir(dirbuf,dirbufsize) 78 | char *dirbuf; 79 | unsigned dirbufsize; 80 | { 81 | short count, limit, dirsort(), dircode, ksize, i; 82 | unsigned size; 83 | char filename[15]; 84 | char *p, *q; 85 | struct sortentry *se; 86 | struct fcb srcfcb; 87 | 88 | q = dirbuf; 89 | Lines = 2; 90 | memset(&srcfcb,0,sizeof(struct fcb)); 91 | memset(srcfcb.name,'?',8); /* all filenames, all extents */ 92 | memset(srcfcb.ft,'?',3); 93 | srcfcb.ex = '?'; 94 | limit = dirbufsize / sizeof(struct sortentry); /* how many */ 95 | dircode = bdos(CPMFFST,&srcfcb); /* search first */ 96 | count = 0; 97 | while (dircode != -1) { 98 | p = ((char *) CPMBUF + dircode * 32); 99 | if ((*(p+10) & 0x80) == 0) { /* don't list $SYS files */ 100 | for (i = 0; i < 16; i++) { 101 | *q++ = *p++ & ((i > 0 && i < 12) ? 0x7f : 0xff); 102 | } 103 | if (count == limit) { /* can't fit them in */ 104 | free(dirbuf); 105 | unsort_dir(); /* do unsorted directory */ 106 | return; 107 | } 108 | ++count; 109 | } 110 | dircode = bdos(CPMFNXT,&srcfcb); /* search next */ 111 | } 112 | qsort(dirbuf,count,16,dirsort); /* sort in alpha order */ 113 | 114 | /* ok, now print them all */ 115 | se = (struct sortentry *) dirbuf; 116 | for (i = Entries = 0; i < count; i++) { 117 | if (!i || memcmp(se, se - 1, 12)) { 118 | size = se->rc + (se->s2 * 32 + se->ex) * 128; 119 | ksize = (size / 8) + ((size % 8) ? 1 : 0); 120 | memcpy(filename,se->name,8); 121 | filename[8] = '.'; 122 | memcpy(filename + 9,se->type,3); 123 | filename[12] = '\0'; 124 | printf("%s%4dk",filename,ksize); 125 | if (printsep(SORTCOLS)) { 126 | break; 127 | } 128 | Entries++; 129 | } 130 | se++; 131 | } 132 | free(dirbuf); 133 | if (Entries % SORTCOLS) { 134 | printf("\n"); 135 | } 136 | } 137 | 138 | /* Do unsorted directory */ 139 | void unsort_dir() 140 | { 141 | short dircode, i; 142 | struct direntry *dp; 143 | 144 | Lines = 2; 145 | dircode = getfirst("????????.???"); 146 | for (Entries = 0; dircode != 0xff; Entries++) { 147 | dp = (struct direntry *) (CPMBUF + dircode * 32); 148 | memcpy(Pathname,dp->flname,8); 149 | Pathname[8]= '.'; 150 | memcpy(Pathname+9,dp->ftype,3); 151 | Pathname[12] = '\0'; 152 | for (i = 0; i < 11; i++) /* remove attributes */ 153 | Pathname[i] = Pathname[i] & 0x7f; 154 | printf("%s",Pathname); 155 | if (printsep(UNSORTCOLS)) { 156 | break; 157 | } 158 | dircode = getnext(); 159 | } 160 | if (Entries % UNSORTCOLS) 161 | printf("\n"); 162 | } 163 | 164 | /* Print separator between directory entries. Do [more] if page full */ 165 | /* Return TRUE if end of page and ctl-c or ctl-k typed */ 166 | int printsep(count) 167 | short count; 168 | { 169 | if ((Entries % count) == count - 1) { 170 | printf("\n"); 171 | if (++Lines == DIRLINES) { /* bump line count */ 172 | Lines = 0; /* pause if done a page */ 173 | return domore(); /* then do [more] */ 174 | } 175 | } else { 176 | printf(" | "); 177 | } 178 | return FALSE; 179 | } 180 | 181 | /* Print [more] and wait for a key. Return TRUE if user hit ctl-c or ctl-k */ 182 | int domore() 183 | { 184 | char c; 185 | 186 | printf("[more]"); 187 | flush(); 188 | while (!(c = bdos(CPMDCIO,0xFF))); /* loop till we get one */ 189 | printf("\b\b\b\b\b\b \b\b\b\b\b\b"); 190 | return c == CTRLC || c == CTRLK; 191 | } 192 | 193 | /* Function for qsort to compare two directory entries */ 194 | int dirsort(p1,p2) 195 | char *p1, *p2; 196 | { 197 | short j; 198 | 199 | if (j = memcmp(p1,p2,12)) 200 | return j; 201 | 202 | /* Both are the same file -- sort on extent */ 203 | if ((j = (p1[14] * 32 + p1[12]) - (p2[14] * 32 + p2[12])) > 0) 204 | return -1; 205 | else 206 | return 1; 207 | } 208 | 209 | int cntbits(byte) 210 | char byte; 211 | { 212 | int i,count; 213 | 214 | for (count=i=0; i<8; i++) { 215 | count += (byte & 1); 216 | byte >>= 1; 217 | } 218 | return count; 219 | } 220 | 221 | void resetace() /* to default values */ 222 | { 223 | Current.cbaudindex = Line.baudindex; 224 | Current.cparity = Line.parity; 225 | Current.cdatabits = Line.databits; 226 | Current.cstopbits = Line.stopbits; 227 | updateace(); 228 | } 229 | 230 | void updateace() 231 | { 232 | initace(Current.cbaudindex,Current.cparity, 233 | Current.cdatabits,Current.cstopbits); 234 | } 235 | 236 | void hangup() 237 | { 238 | char c; 239 | 240 | stndout(); 241 | printf("\n ZMP: Disconnect (Y/N) ? \007"); 242 | stndend(); 243 | c = dio(); 244 | if (c != 'Y' && c != 'y' ) { 245 | printf("\n"); 246 | return; 247 | } 248 | printf("\nHanging up...\n"); 249 | dtroff(); /* Turn DTR off for a bit */ 250 | mswait(200); /* Like 200 ms */ 251 | dtron(); /* Then back on again */ 252 | mstrout(Modem.hangup,FALSE); 253 | resetace(); 254 | } 255 | 256 | /* Prompt user and get any key */ 257 | char waitakey() 258 | { 259 | char c; 260 | 261 | printf("\n Any key to continue: "); 262 | flush(); 263 | while (!(c = bdos(CPMDCIO,0xFF))); 264 | return c; 265 | } 266 | 267 | /* End of TERM module */ 268 |  -------------------------------------------------------------------------------- /src/zmterm4.c: -------------------------------------------------------------------------------- 1 | /* TERM module File #4 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "zmp.h" 8 | 9 | extern int getch(); 10 | extern char *alloc(int); 11 | extern int allocerror(void *); 12 | extern int readstr(char *,int); 13 | extern int readline(int); 14 | extern int getline(char *, unsigned); 15 | extern int kbwait(unsigned); 16 | extern int isin(char *, char *); 17 | 18 | static int shownos(); 19 | static int loadnos(); 20 | 21 | void setace(n) /* for a particular phone call */ 22 | int n; 23 | { 24 | Current.cbaudindex = Book[n].pbaudindex; 25 | Current.cparity = Book[n].pparity; 26 | Current.cdatabits = Book[n].pdatabits; 27 | Current.cstopbits = Book[n].pstopbits; 28 | updateace(); 29 | } 30 | 31 | int gettimedchar(seconds) 32 | unsigned seconds; 33 | { 34 | unsigned t; 35 | int c; 36 | 37 | t = seconds * 10; 38 | while(!(c=getch()) && (t--)) { 39 | mswait(100); 40 | } 41 | return c ? c : TIMEOUT; 42 | } 43 | 44 | 45 | int dial() 46 | { 47 | static char *number; /* buffer for number to be sent to modem */ 48 | static char *result; /* buffer for responses from modem */ 49 | static char *instr; /* buffer for numbers entered at keyboard */ 50 | static int connect; 51 | static int status, i, j, n, nocnt, action, c; 52 | static char *p; 53 | 54 | if (allocerror(number = alloc(128))) { 55 | return; 56 | } 57 | if (allocerror(result = alloc(128))) { 58 | free(number); 59 | return; 60 | } 61 | if (allocerror(instr = alloc(128))) { 62 | free(number); 63 | free(result); 64 | return; 65 | } 66 | QuitFlag = connect = FALSE; 67 | Dialing = TRUE; 68 | status = gettimedchar(5); 69 | if (status != TIMEOUT) { 70 | instr[0] = status; 71 | instr[1] = '\000'; 72 | j = 1; 73 | status = loadnos(); 74 | } else { 75 | status = shownos(); 76 | printf("\nEnter letters and/or numbers, separated by commas..\n: "); 77 | j=getline(instr,80); 78 | } 79 | if (j) { 80 | putlabel("Automatic Redial: Press ESC to stop"); 81 | for (i=0,nocnt=1; instr[i]; i++) 82 | if (instr[i] == ',') { 83 | instr[i] = 0; 84 | nocnt++; 85 | } 86 | i = nocnt; 87 | for (;;) { 88 | p = instr; 89 | nocnt = i; 90 | while (nocnt--) { 91 | n = -1; 92 | strcpy(number,Modem.dialcmd); 93 | if ((status == OK) && (j=strlen(p))==1) { 94 | n = *p; 95 | if (isalpha(n) && toupper(n)<='T' ) { 96 | n = toupper(n) - 'A'; 97 | p = Book[n].number; 98 | if (*p != '_') { 99 | setace(n); 100 | strcat(number,p); 101 | strcat(number,Modem.dialsuffix); 102 | mstrout(number,FALSE); 103 | p = Book[n].name; 104 | printf("\nDialing %s...", p); 105 | } else { 106 | printf("\nInvalid Number\n"); 107 | goto abort; 108 | } 109 | } else { 110 | printf("\nInvalid Number\n"); 111 | goto abort; 112 | } 113 | } else { 114 | strcat(number,p); 115 | strcat(number,Modem.dialsuffix); 116 | mstrout(number,FALSE); 117 | printf("\nDialing %s...",p); 118 | } 119 | /* flush modem input */ 120 | while (readline(10) != TIMEOUT); 121 | do { 122 | action = readstr(result,Modem.timeout); 123 | if (action == TIMEOUT) { 124 | goto abort; 125 | } 126 | printf("%s\n",result); 127 | } while (!(c=isin(result,Modem.connect)) 128 | && !isin(result,Modem.busy1) 129 | && !isin(result,Modem.busy2) 130 | && !isin(result,Modem.busy3) 131 | && !isin(result,Modem.busy4)); 132 | 133 | if (c) { /* got connect string */ 134 | printf("\007\nOn Line to %s\n", p); 135 | if (n >= 0) { 136 | FDx = !Book[n].echo; 137 | } 138 | connect = TRUE; 139 | goto done; 140 | } 141 | mcharout(CR); 142 | /* wait for modem */ 143 | while (readline(10) != TIMEOUT); 144 | p += j+1; 145 | } 146 | if (kbwait(Modem.pause)) { 147 | goto abort; 148 | } 149 | } 150 | } 151 | 152 | abort: 153 | printf("Call Aborted.\n"); 154 | mcharout(CR); 155 | readstr(result,1); /*gobble last result*/ 156 | resetace(); 157 | 158 | done: 159 | flush(); 160 | if (Book != (struct phonebook *) MEMORY_FULL) { 161 | free(Book); 162 | } 163 | free(instr); 164 | free(result); 165 | free(number); 166 | Dialing = FALSE; 167 | return connect; 168 | } 169 | 170 | static int shownos() 171 | { 172 | static int i, j, status; 173 | 174 | cls(); 175 | if ((status=loadnos()) == OK) { 176 | stndout(); 177 | printf(" NAME NUMBER B P D S E"); 178 | stndend(); 179 | for (i=0,j=1; i<20; i++,j++) { 180 | locate(i+1,0); 181 | printf("%c - %s",i+'A',Book[i].name); 182 | locate(i+1,41-strlen(Book[i].number)); 183 | printf(Book[i].number); 184 | locate(i+1,44); 185 | printf("%4u0 %c", 186 | Baudtable[Book[i].pbaudindex], 187 | Book[i].pparity); 188 | printf(" %d %d %c\n", 189 | Book[i].pdatabits, 190 | Book[i].pstopbits, 191 | Book[i].echo ? 'H' : 'F'); 192 | } 193 | } 194 | return status; 195 | } 196 | 197 | static int loadnos() 198 | { 199 | static unsigned amount; 200 | char dummy; 201 | int i,result; 202 | FILE *fd; 203 | 204 | result = NERROR; 205 | amount = 21 * sizeof(struct phonebook); 206 | Book = (struct phonebook *) alloc(amount); 207 | if (!allocerror(Book)) { 208 | strcpy(Pathname,Phonefile); 209 | addu(Pathname,Overdrive,Overuser); 210 | fd = fopen(Pathname,"r"); 211 | if (fd) { 212 | for (i = 0; i < 20; i++) { 213 | fgets(Book[i].name,17,fd); 214 | fscanf(fd,"%c %s %d %c", 215 | &dummy, 216 | Book[i].number, 217 | &Book[i].pbaudindex, 218 | &Book[i].pparity); 219 | fscanf(fd,"%d %d %d", 220 | &Book[i].pdatabits, 221 | &Book[i].pstopbits, 222 | &Book[i].echo); 223 | fgetc(fd); /* remove LF */ 224 | } 225 | fclose(fd); 226 | result = OK; 227 | } 228 | } 229 | return result; 230 | } 231 | /* End of TERM module */ 232 | /* End of TERM module File 1 */ 233 |  -------------------------------------------------------------------------------- /src/zmxfer.lnk: -------------------------------------------------------------------------------- 1 | -c40d2h -ptext=40d2h,data -ozmxfer.ovr -mzmxfer.map \ 2 | ZMXFER.OBJ ZMXFER2A.OBJ ZMXFER2B.OBJ ZMXFER2C.OBJ ZMXFER2D.OBJ ZMXFER2E.OBJ \ 3 | ZMXFER2F.OBJ ZMXFER2G.OBJ ZMXFER2H.OBJ ZMXFER2I.OBJ ZMXFER2J.OBJ ZMXFER3A.OBJ \ 4 | ZMXFER3B.OBJ ZMXFER3C.OBJ ZMXFER3D.OBJ ZMXFER3E.OBJ ZMXFER3F.OBJ ZMXFER3G.OBJ \ 5 | ZMXFER3H.OBJ ZMXFER3I.OBJ ZMXFER4A.OBJ ZMXFER4B.OBJ ZMXFER4C.OBJ ZMXFER4D.OBJ \ 6 | ZMXFER4E.OBJ ZMXFER4F.OBJ ZMXFER4G.OBJ ZMXFER5A.OBJ ZMXFER5B.OBJ ZMXFER5C.OBJ \ 7 | ZMXFER5D.OBJ ZMXFER5E.OBJ ZMXFER5F.OBJ ZMXFER5G.OBJ ZMXFER5H.OBJ ZMXFER5I.OBJ \ 8 | ZMXFER5J.OBJ ZMXFER5K.OBJ ZMXFER5L.OBJ ZMXFER5M.OBJ ZMXFER5N.OBJ ZMXFER5O.OBJ \ 9 | ZMXFER5P.OBJ zzm.obj zzm2.obj main.obj a:libx.lib \ 10 | a:libc.lib 11 |  -------------------------------------------------------------------------------- /src/zmxfer1.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/src/zmxfer1.com -------------------------------------------------------------------------------- /src/zmxfer2.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/src/zmxfer2.com -------------------------------------------------------------------------------- /src/zmxfer2a.c: -------------------------------------------------------------------------------- 1 | /************************ START OF XFER MODULE 2 ****************************/ 2 | 3 | /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include "zmp.h" 8 | #include "zmodmdef.h" 9 | 10 | extern void slabel(); 11 | extern char *alloc(int); 12 | extern int allocerror(void *); 13 | extern char *grabmem(unsigned *); 14 | extern void savecurs(); 15 | extern void hidecurs(); 16 | extern void box(); 17 | extern void report(int,char *); 18 | extern void stohdr(long); 19 | extern void zshhdr(int,char *); 20 | extern int getzrxinit(); 21 | extern void clrreports(); 22 | extern int opabort(); 23 | extern int wcs(char *); 24 | extern void tfclose(); 25 | extern void canit(); 26 | extern void zperr(char *,int); 27 | extern void saybibi(); 28 | extern void wctxpn(char *); 29 | extern void showcurs(); 30 | extern void restcurs(); 31 | 32 | char *Rxptr; 33 | int Tryzhdrtype; 34 | int Beenhereb4; 35 | unsigned Rxbuflen = 16384; /* Receiver's max buffer length */ 36 | int Noeofseen = 0; 37 | int Totsecs; /* total number of sectors this file */ 38 | char *Txbuf; 39 | int Filcnt; /* count of number of files opened */ 40 | long Bytcnt; 41 | long Lastread; /* Beginning offset of last buffer read */ 42 | int Lastn; /* Count of last buffer read or -1 */ 43 | int Dontread; /* Don't read the buffer, it's still there */ 44 | int Incnt; /* count for chars not read from the Cpmbuf */ 45 | struct stat Fs; 46 | 47 | long Lrxpos; /* Receiver's last reported offset */ 48 | int Errors; 49 | int Lastrx; 50 | int Firstsec; 51 | int Eofseen; /* indicates cpm eof (^Z) has been received */ 52 | int Fd; 53 | char *Cpmbuf; /* buffer bytes for writing to disk */ 54 | unsigned Cpbufsize; /* size of Cpmbuf */ 55 | unsigned Cpindex = 0; /* index for Cpmbuf */ 56 | char *Secbuf; /* sector buffer receiving */ 57 | int Zctlesc; /* Encode control characters */ 58 | int Rxtimeout = 100; /* Tenths of seconds to wait for something */ 59 | int Rxtype; /* Type of header received */ 60 | int Rxcount; /* Count of data bytes received */ 61 | char Rxhdr[4]; /* Received header */ 62 | char Txhdr[4]; /* Transmitted header */ 63 | long Rxpos; /* Received file position */ 64 | long Txpos; /* Transmitted file position */ 65 | int Txfcs32; /* TRUE means send binary frames with 32 bit FCS */ 66 | int Crc32t; /* Display flag indicating 32 bit CRC being sent */ 67 | int Crc32; /* Display flag indicating 32 bit CRC being received */ 68 | char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */ 69 | int Baudrate; 70 | 71 | wcsend(argc, argp) 72 | int argc; /* nr of files to send */ 73 | char *argp[]; /* list of file names */ 74 | { 75 | int n, status; 76 | 77 | slabel(); 78 | Zctlesc = 0; 79 | Incnt = 0; 80 | Baudrate = Baudtable[Current.cbaudindex]; 81 | Filcnt = Errors = 0; 82 | 83 | Fd = -1; 84 | 85 | Txbuf = alloc(KSIZE); 86 | if (allocerror(Txbuf)) { 87 | return NERROR; 88 | } 89 | Cpmbuf = grabmem(&Cpbufsize); 90 | if (allocerror(Cpmbuf)) { 91 | return NERROR; 92 | } 93 | Cpindex = 0; /* just in case */ 94 | Crcflag = FALSE; 95 | Firstsec = TRUE; 96 | Bytcnt = -1; 97 | Rxtimeout = 600; 98 | savecurs(); 99 | hidecurs(); 100 | box(); 101 | status = NERROR; 102 | report(PROTOCOL,Xmodem?"XMODEM Send":Zmodem?"ZMODEM Send":"YMODEM Send"); 103 | if (Zmodem) { 104 | stohdr(0L); 105 | zshhdr(ZRQINIT, Txhdr); 106 | if (getzrxinit()==NERROR) 107 | goto badreturn; 108 | } 109 | for (n=0; n 6 | #include 7 | #include 8 | #include "zmp.h" 9 | #include "zmodmdef.h" 10 | 11 | extern void zperr(char *,int); 12 | extern void wait(int); 13 | extern void fstat(char *,struct stat *); 14 | extern int wctxpn(char *); 15 | extern void canit(); 16 | extern int wctx(long); 17 | 18 | extern int Fd; 19 | extern int Noeofseen; 20 | extern long Lastread; 21 | extern int Lastn; 22 | extern int Dontread; 23 | extern int Filcnt; 24 | extern struct stat Fs; 25 | 26 | int wcs(oname) 27 | char *oname; 28 | { 29 | unsigned length; 30 | long flen; 31 | 32 | if ((Fd=open(oname,0))==UBIOT) { 33 | zperr("Can't open file",TRUE); 34 | wait(2); 35 | return OK; /* pass over it, there may be others */ 36 | } 37 | ++Noeofseen; 38 | Lastread = 0L; 39 | Lastn = -1; 40 | Dontread = FALSE; 41 | ++Filcnt; 42 | fstat(oname,&Fs); 43 | switch (wctxpn(oname)) { /* transmit path name */ 44 | case NERROR: 45 | if (Zmodem) { 46 | canit(); /* Send CAN */ 47 | } 48 | return NERROR; 49 | 50 | case ZSKIP: 51 | return OK; 52 | } 53 | length = Fs.records; 54 | flen = (long)length * 128; 55 | if (!Zmodem && wctx(flen)==NERROR) 56 | return NERROR; 57 | return 0; 58 | } 59 | 60 | /************************** END OF MODULE 7 *********************************/ 61 |  -------------------------------------------------------------------------------- /src/zmxfer2c.c: -------------------------------------------------------------------------------- 1 | /************************ START OF XFER MODULE 2 ****************************/ 2 | 3 | /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "zmp.h" 9 | #include "zmodmdef.h" 10 | 11 | extern void report(int,char *); 12 | extern void lreport(int,long); 13 | extern void dreport(int,int); 14 | extern int getnak(); 15 | extern void deldrive(char *); 16 | extern int zsendfile(char *,int); 17 | extern int wcputsec(char *,int,int); 18 | extern char *ttime(long); 19 | extern void zperr(char *,int); 20 | 21 | extern char *Txbuf; 22 | extern struct stat Fs; 23 | 24 | /* 25 | * generate and transmit pathname block consisting of 26 | * pathname (null terminated), 27 | * file length, modification time and file mode 28 | * in octal. 29 | * N.B.: modifies the passed name, may extend it! 30 | */ 31 | int wctxpn(name) 32 | char *name; 33 | { 34 | static char *p; 35 | static unsigned length; 36 | static long nrbytes; 37 | 38 | memset(Txbuf,'\0',KSIZE); 39 | p = Txbuf; 40 | if (*name) { 41 | length = Fs.records; 42 | nrbytes = (long)length * 128; 43 | report(PATHNAME,name); 44 | lreport(FILESIZE,nrbytes); 45 | dreport(FBLOCKS,length); 46 | report(SENDTIME,ttime(nrbytes)); 47 | if (Xmodem) { /* xmodem, don't send path name */ 48 | return OK; 49 | } 50 | if (!Zmodem) { 51 | Blklen = KSIZE; 52 | if (getnak()) { 53 | return NERROR; 54 | } 55 | } 56 | strcpy(Txbuf,name); 57 | deldrive(Txbuf); /* remove drive ind if any */ 58 | p = Txbuf + strlen(Txbuf); 59 | ++p; 60 | sprintf(p,"%lu %lo 100644",nrbytes,Fs.modtime); 61 | } 62 | if (Zmodem) { 63 | return zsendfile(Txbuf, 1+strlen(p)+(p-Txbuf)); 64 | } 65 | if (wcputsec(Txbuf, 0, SECSIZ)==NERROR) { 66 | return NERROR; 67 | } 68 | return OK; 69 | } 70 | 71 | /************************** END OF MODULE 7 *********************************/ 72 |  -------------------------------------------------------------------------------- /src/zmxfer2d.c: -------------------------------------------------------------------------------- 1 | /************************ START OF XFER MODULE 2 ****************************/ 2 | 3 | /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | 7 | /* itoa - convert n to characters in s. */ 8 | char *itoa(n, s) 9 | short n; 10 | char *s; 11 | { 12 | static short c, k; 13 | static char *p, *q; 14 | 15 | if ((k = n) < 0) { /* record sign */ 16 | n = -n; /* make n positive */ 17 | } 18 | q = p = s; 19 | do { /* generate digits in reverse order */ 20 | *p++ = n % 10 + '0'; /* get next digit */ 21 | } while ((n /= 10) > 0); /* delete it */ 22 | if (k < 0) { 23 | *p++ = '-'; 24 | } 25 | *p = 0; 26 | /* reverse string in place */ 27 | while (q < --p) { 28 | c = *q; *q++ = *p; *p = c; 29 | } 30 | return s; 31 | } 32 | 33 | /************************** END OF MODULE 7 *********************************/ 34 |  -------------------------------------------------------------------------------- /src/zmxfer2e.c: -------------------------------------------------------------------------------- 1 | /************************ START OF XFER MODULE 2 ****************************/ 2 | 3 | /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | 7 | /* ltoa - convert n to characters in s. */ 8 | char *ltoa(n, s) 9 | char *s; 10 | long n; 11 | { 12 | static long c, k; 13 | static char *p, *q; 14 | 15 | if ((k = n) < 0) { /* record sign */ 16 | n = -n; /* make n positive */ 17 | } 18 | q = p = s; 19 | do { /* generate digits in reverse order */ 20 | *p++ = n % 10 + '0'; /* get next digit */ 21 | } while ((n /= 10) > 0); /* delete it */ 22 | if (k < 0) { 23 | *p++ = '-'; 24 | } 25 | *p = 0; 26 | /* reverse string in place */ 27 | while (q < --p) { 28 | c = *q; 29 | *q++ = *p; 30 | *p = c; 31 | } 32 | return s; 33 | } 34 | 35 | /************************** END OF MODULE 7 *********************************/ 36 |  -------------------------------------------------------------------------------- /src/zmxfer2f.c: -------------------------------------------------------------------------------- 1 | /************************ START OF XFER MODULE 2 ****************************/ 2 | 3 | /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include "zmp.h" 8 | #include "zmodmdef.h" 9 | 10 | extern int opabort(); 11 | extern int readock(int,int); 12 | extern int getzrxinit(); 13 | extern void report(int,char *); 14 | 15 | extern int Lastrx; 16 | 17 | int getnak() 18 | { 19 | static int firstch; 20 | 21 | Lastrx = 0; 22 | for (;;) { 23 | if (opabort()) { 24 | return NERROR; 25 | } 26 | firstch = readock(800,1); 27 | if (firstch==ZPAD) { 28 | if (getzrxinit()) { 29 | return NERROR; 30 | } 31 | break; 32 | } else if (firstch==TIMEOUT) { 33 | zperr("Timeout on PName",TRUE); 34 | return TRUE; 35 | } else if (firstch==WANTCRC) { 36 | Crcflag = TRUE; 37 | break; 38 | } else if (firstch==NAK) { 39 | break; 40 | } else if (firstch==CAN) { 41 | if ((firstch = readock(20,1)) == CAN && Lastrx == CAN) { 42 | return TRUE; 43 | } 44 | } 45 | Lastrx = firstch; 46 | } 47 | report(BLKCHECK,Crcflag?"CRC":"Checksum"); 48 | return FALSE; 49 | } 50 | 51 | /************************** END OF MODULE 7 *********************************/ 52 |  53 | ; /* Spacing between zcrcq requests */ 54 | unsigned Txwcnt; /* -------------------------------------------------------------------------------- /src/zmxfer2g.c: -------------------------------------------------------------------------------- 1 | /************************ START OF XFER MODULE 2 ****************************/ 2 | 3 | /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "zmp.h" 11 | #include "zmodmdef.h" 12 | 13 | extern int readock(int,int); 14 | extern int opabort(); 15 | extern int filbuf(char *,int); 16 | extern int wcputsec(char *,int,int); 17 | 18 | extern int Firstsec; 19 | extern int Rxtimeout; 20 | extern char *Txbuf; 21 | 22 | int wctx(flen) 23 | long flen; 24 | { 25 | static int thisblklen, i; 26 | static unsigned sectnum, attempts, firstch; 27 | static long charssent; 28 | 29 | charssent = 0L; 30 | Firstsec = TRUE; 31 | thisblklen = Blklen; 32 | i = 0; 33 | 34 | while ((firstch=readock(1,2)) != NAK 35 | && firstch != WANTCRC 36 | && firstch != CAN 37 | && !opabort() 38 | && ++i < Rxtimeout) { 39 | ; 40 | } 41 | if (QuitFlag) { 42 | return NERROR; 43 | } 44 | if (firstch==CAN) { 45 | zperr("Rcvr CANcelled",TRUE); 46 | return NERROR; 47 | } 48 | if (firstch==WANTCRC) { 49 | Crcflag=TRUE; 50 | } 51 | report(BLKCHECK,Crcflag?"CRC":"Checksum"); 52 | sectnum=0; 53 | for (;;) { 54 | if (opabort()) { 55 | return NERROR; 56 | } 57 | if (flen <= (charssent + 896L)) { 58 | Blklen = thisblklen = 128; 59 | } 60 | if ( !filbuf(Txbuf, thisblklen)) { 61 | break; 62 | } 63 | purgeline(); /* ignore anything got while loading */ 64 | if (wcputsec(Txbuf, ++sectnum, thisblklen)==NERROR) { 65 | return NERROR; 66 | } 67 | charssent += thisblklen; 68 | sreport(sectnum,charssent); 69 | } 70 | attempts=0; 71 | do { 72 | dreport(ERRORS,attempts); 73 | purgeline(); 74 | mcharout(EOT); 75 | ++attempts; 76 | } while ((firstch=(readock(Rxtimeout, 1)) != ACK) 77 | && attempts < RETRYMAX 78 | && !opabort() ); 79 | if (attempts == RETRYMAX) { 80 | zperr("No ACK on EOT",TRUE); 81 | return NERROR; 82 | } else if (QuitFlag) { /* from opabort */ 83 | return NERROR; 84 | } else { 85 | return OK; 86 | } 87 | } 88 | 89 | /************************** END OF MODULE 7 *********************************/ 90 |  -------------------------------------------------------------------------------- /src/zmxfer2h.c: -------------------------------------------------------------------------------- 1 | /************************ START OF XFER MODULE 2 ****************************/ 2 | 3 | /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include "zmp.h" 8 | #include "zmodmdef.h" 9 | 10 | extern int dreport(int,int); 11 | extern int opabort(); 12 | extern void mcharout(char); 13 | extern unsigned updcrc(unsigned,unsigned); 14 | extern int readock(int,int); 15 | extern void zperr(char *,int); 16 | 17 | extern int Lastrx; 18 | extern int Rxtimeout; 19 | extern int Firstsec; 20 | extern int Crcflag; 21 | extern int Totsecs; 22 | extern int Noeofseen; 23 | 24 | int wcputsec(buf, sectnum, cseclen) 25 | char *buf; 26 | int sectnum; 27 | int cseclen; /* data length of this sector to send */ 28 | { 29 | static unsigned checksum; 30 | static char *cp; 31 | static unsigned oldcrc; 32 | static int wcj; 33 | static int firstch; 34 | static int attempts; 35 | 36 | firstch=0; /* part of logic to detect CAN CAN */ 37 | 38 | dreport(ERRORS,0); 39 | for (attempts=0; attempts <= RETRYMAX; attempts++) { 40 | if (opabort()) { 41 | return NERROR; 42 | } 43 | if (attempts) { 44 | dreport(ERRORS,attempts); 45 | } 46 | Lastrx= firstch; 47 | mcharout(cseclen==KSIZE?STX:SOH); 48 | mcharout(sectnum); 49 | mcharout(0xFF & ~sectnum); 50 | oldcrc=checksum=0; 51 | for (wcj=cseclen,cp=buf; --wcj>=0; ) { 52 | mcharout(*cp); 53 | oldcrc=updcrc((0377& *cp), oldcrc); 54 | checksum += *cp++; 55 | } 56 | if (Crcflag) { 57 | oldcrc=updcrc(0,updcrc(0,oldcrc)); 58 | mcharout((int)oldcrc>>8); 59 | mcharout((int)oldcrc); 60 | } else { 61 | mcharout(checksum); 62 | } 63 | 64 | firstch = readock(Rxtimeout, (Noeofseen&§num) ? 2:1); 65 | gotnak: 66 | switch (firstch) { 67 | case CAN: 68 | if(Lastrx == CAN) { 69 | cancan: 70 | zperr("Rcvr CANcelled",TRUE); 71 | return NERROR; 72 | } 73 | break; 74 | case TIMEOUT: 75 | zperr("Timeout on ACK",TRUE); 76 | continue; 77 | case WANTCRC: 78 | if (Firstsec) { 79 | Crcflag = TRUE; 80 | } 81 | report(BLKCHECK,Crcflag?"CRC":"Checksum"); 82 | case NAK: 83 | zperr("NAK on sector",TRUE); 84 | continue; 85 | case ACK: 86 | Firstsec=FALSE; 87 | Totsecs += (cseclen>>7); 88 | return OK; 89 | case NERROR: 90 | zperr("Got burst",TRUE); 91 | break; 92 | default: 93 | zperr("Bad sector ACK",TRUE); 94 | break; 95 | } 96 | for (;;) { 97 | if (opabort()) { 98 | return NERROR; 99 | } 100 | Lastrx = firstch; 101 | if ((firstch = readock(Rxtimeout, 2)) == TIMEOUT) { 102 | break; 103 | } 104 | if (firstch == NAK || firstch == WANTCRC) { 105 | goto gotnak; 106 | } 107 | if (firstch == CAN && Lastrx == CAN) { 108 | goto cancan; 109 | } 110 | } 111 | } 112 | zperr("Retry Exceeded",TRUE); 113 | return NERROR; 114 | } 115 | 116 | /************************** END OF MODULE 7 *********************************/ 117 |  -------------------------------------------------------------------------------- /src/zmxfer2i.c: -------------------------------------------------------------------------------- 1 | /************************ START OF XFER MODULE 2 ****************************/ 2 | 3 | /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include "zmp.h" 8 | 9 | extern int newload(char *,int); 10 | 11 | /* fill buf with count chars padding with ^Z for CPM */ 12 | 13 | int filbuf(buf, count) 14 | char *buf; 15 | int count; 16 | { 17 | static int c, m; 18 | 19 | c = m = newload(buf, count); 20 | if (m <= 0) { 21 | return 0; 22 | } 23 | while (m < count) { 24 | buf[m++] = CTRLZ; 25 | } 26 | return c; 27 | } 28 | 29 | /************************** END OF MODULE 7 *********************************/ 30 |  -------------------------------------------------------------------------------- /src/zmxfer2j.c: -------------------------------------------------------------------------------- 1 | /************************ START OF XFER MODULE 2 ****************************/ 2 | 3 | /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | 8 | extern int Fd; 9 | extern char *Cpmbuf; 10 | extern unsigned Cpbufsize; 11 | extern unsigned Cpindex; 12 | extern int Incnt; 13 | 14 | int newload(buf, count) 15 | int count; 16 | char *buf; 17 | { 18 | static int j; 19 | 20 | j = 0; 21 | while (count--) { 22 | if (Incnt <= 0) { 23 | Incnt = read( Fd, Cpmbuf, Cpbufsize ); 24 | Cpindex = 0; 25 | if (Incnt <= 0) { 26 | break; 27 | } 28 | } 29 | buf[j++] = Cpmbuf[Cpindex++]; 30 | --Incnt; 31 | } 32 | return (j ? j : -1); 33 | } 34 | 35 | /************************** END OF MODULE 7 *********************************/ 36 |  -------------------------------------------------------------------------------- /src/zmxfer3.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/src/zmxfer3.com -------------------------------------------------------------------------------- /src/zmxfer3a.c: -------------------------------------------------------------------------------- 1 | /************************* START OF XFER MODULE 3 ***************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | #include "zmodmdef.h" 7 | 8 | extern int opabort(); 9 | extern int zgethdr(char *,int); 10 | extern void stohdr(long); 11 | extern void zshhdr(int,char *); 12 | extern int sendzsinit(); 13 | 14 | extern unsigned Rxbuflen; 15 | extern long Rxpos; 16 | extern char Rxhdr[4]; 17 | extern char Txhdr[4]; 18 | extern int Txfcs32; 19 | extern int Zctlesc; 20 | 21 | /* 22 | * Get the receiver's init parameters 23 | */ 24 | 25 | int getzrxinit() 26 | { 27 | int n,hdr; 28 | int Rxflags; 29 | 30 | for (n=10; --n>=0; ) { 31 | if (opabort()) { 32 | return NERROR; 33 | } 34 | hdr = zgethdr(Rxhdr, 1); 35 | if (hdr==ZCHALLENGE) { /* Echo receiver's challenge numbr */ 36 | stohdr(Rxpos); 37 | zshhdr(ZACK, Txhdr); 38 | continue; 39 | } else if (hdr==ZCOMMAND) { /* They didn't see out ZRQINIT */ 40 | stohdr(0L); 41 | zshhdr(ZRQINIT, Txhdr); 42 | continue; 43 | } else if (hdr==ZRINIT) { 44 | Rxflags = 0377 & Rxhdr[ZF0]; 45 | Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32)); 46 | Zctlesc |= Rxflags & TESCCTL; 47 | Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8); 48 | return (sendzsinit()); 49 | } else if (hdr==ZCAN || hdr==TIMEOUT) { 50 | return NERROR; 51 | } else if (hdr==ZRQINIT) { 52 | if (Rxhdr[ZF0] == ZCOMMAND) { 53 | continue; 54 | } 55 | } else { 56 | zshhdr(ZNAK, Txhdr); 57 | continue; 58 | } 59 | } 60 | return NERROR; 61 | } 62 | /************************** END OF MODULE 7A *********************************/ 63 |  -------------------------------------------------------------------------------- /src/zmxfer3b.c: -------------------------------------------------------------------------------- 1 | /************************* START OF XFER MODULE 3 ***************************/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include "zmp.h" 7 | #include "zmodmdef.h" 8 | 9 | extern void stohdr(long); 10 | extern int opabort(); 11 | extern void zsbhdr(int,char *); 12 | extern void zsdata(char *,int,int); 13 | extern int zgethdr(char *,int); 14 | extern void zperr(char *,int); 15 | 16 | extern char *Txbuf; 17 | extern char Rxhdr[4]; 18 | extern char Txhdr[4]; 19 | 20 | /* 21 | * Attention string to be executed by receiver to interrupt streaming data 22 | * when an error is detected. A pause (0336) may be needed before the 23 | * ^C (03) or after it. 0337 causes a break to be sent. 24 | */ 25 | #define SLEEP 0336 26 | static char Myattn[] = { CTRLC,SLEEP,0 }; 27 | 28 | /* Send send-init information */ 29 | 30 | int sendzsinit() 31 | { 32 | int tries; 33 | 34 | stohdr(0L); /* All flags are undefined */ 35 | strcpy(Txbuf,Myattn); /* Copy Attn string */ 36 | for (tries = 0; tries < 20; tries++) { 37 | if (opabort()) { 38 | return NERROR; 39 | } 40 | zsbhdr(ZSINIT,Txhdr); /* Send binary header */ 41 | zsdata(Txbuf,strlen(Txbuf) + 1,ZCRCW); /* Send string */ 42 | if (zgethdr(Rxhdr,0) == ZACK) { 43 | return OK; 44 | } 45 | zperr("Bad ACK: ZSINIT",FALSE); 46 | } 47 | return NERROR; 48 | } 49 | 50 | /************************** END OF MODULE 7A *********************************/ 51 |  -------------------------------------------------------------------------------- /src/zmxfer3c.c: -------------------------------------------------------------------------------- 1 | /************************* START OF XFER MODULE 3 ***************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | #include "zmodmdef.h" 7 | 8 | extern int opabort(); 9 | extern void zsbhdr(int,char *); 10 | extern int readline(int); 11 | extern void clrline(int); 12 | extern int zsndfdata(); 13 | extern int zgethdr(char *,int); 14 | 15 | extern char Rxhdr[4]; 16 | extern char Txhdr[4]; 17 | extern long Lastsync; 18 | extern long Bytcnt; 19 | extern long Rxpos; 20 | extern long Txpos; 21 | extern int Incnt; 22 | extern int Dontread; 23 | extern int Sending; 24 | extern int Fd; 25 | 26 | long Lastsync; 27 | 28 | /* Send file name and related info */ 29 | 30 | int zsendfile(buf, blen) 31 | char *buf; 32 | int blen; 33 | { 34 | static int c; 35 | 36 | for (;;) { 37 | if (opabort()) { 38 | return NERROR; 39 | } 40 | Txhdr[ZF0] = 0; /* file conversion request */ 41 | Txhdr[ZF1] = 0; /* file management request */ 42 | Txhdr[ZF2] = 0; /* file transport request */ 43 | Txhdr[ZF3] = 0; 44 | zsbhdr(ZFILE, Txhdr); 45 | zsdata(buf, blen, ZCRCW); 46 | again: 47 | c = zgethdr(Rxhdr, 1); 48 | if (c==ZRINIT) { 49 | while ((c = readline(INTRATIME)) > 0) { 50 | if (c == ZPAD) { 51 | goto again; 52 | } 53 | } 54 | } else if (c==ZCAN || c==TIMEOUT || c==ZABORT || c==ZFIN) { 55 | return NERROR; 56 | } else if (c==ZSKIP) { 57 | return c; 58 | } else if (c==ZRPOS) { 59 | /* 60 | * Suppress zcrcw request otherwise triggered by 61 | * lastyunc==Bytcnt 62 | */ 63 | Lastsync = (Bytcnt = Txpos = Rxpos) -1L; 64 | 65 | lseek(Fd, Rxpos, 0); /* absolute offset */ 66 | 67 | clrline(KBYTES); 68 | Incnt = 0; 69 | Dontread = FALSE; 70 | c = zsndfdata(); 71 | Sending = FALSE; 72 | return c; 73 | } 74 | } 75 | } 76 | 77 | /************************** END OF MODULE 7A *********************************/ 78 |  -------------------------------------------------------------------------------- /src/zmxfer3d.c: -------------------------------------------------------------------------------- 1 | /************************* START OF XFER MODULE 3 ***************************/ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "zmp.h" 8 | #include "zmodmdef.h" 9 | 10 | extern int getinsync(int); 11 | extern int filbuf(char *,int); 12 | extern int minprdy(); 13 | 14 | extern jmp_buf jb_stop; /* buffer for longjmp */ 15 | extern int Blklen; 16 | extern int Baudrate; 17 | extern long Lrxpos; 18 | extern int Beenhereb4; 19 | extern unsigned Rxbuflen; 20 | extern int Sending; 21 | extern int Firstsec; 22 | extern long Bytcnt; 23 | extern int Crc32t; 24 | extern long Lastsync; 25 | extern long Lastread; 26 | extern char *Txbuf; 27 | extern long Txpos; 28 | extern int Lastn; 29 | extern int Dontread; 30 | extern char Txhdr[4]; 31 | 32 | static int Txwindow; 33 | static int Txwspac; 34 | static int Txwcnt; 35 | 36 | /* Send the data in the file */ 37 | 38 | int zsndfdata() 39 | { 40 | static int c, e, n; 41 | static int newcnt; 42 | static long tcount; 43 | static int junkcount; /* Counts garbage chars received by TX */ 44 | static int nullv = 0; 45 | 46 | tcount = 0L; 47 | Blklen = 128; 48 | if (Baudrate > 30) { 49 | Blklen = 256; 50 | } 51 | if (Baudrate > 120) { 52 | Blklen = 512; 53 | } 54 | if (Baudrate > 240) { 55 | Blklen = KSIZE; 56 | } 57 | if (Rxbuflen && Blklen>Rxbuflen) { 58 | Blklen = Rxbuflen; 59 | } 60 | Lrxpos = 0L; 61 | junkcount = 0; 62 | Beenhereb4 = FALSE; 63 | Sending = Firstsec = TRUE; 64 | somemore: 65 | if (nullv) { 66 | waitack: 67 | junkcount = 0; 68 | c = getinsync(0); 69 | if (QuitFlag) { 70 | return NERROR; 71 | } 72 | gotack: 73 | if (setjmp(jb_stop)) { /* come here if rx stops us */ 74 | rxint: 75 | c = getinsync(1); 76 | } 77 | 78 | switch (c) { 79 | case ZSKIP: 80 | return c; 81 | case ZACK: 82 | case ZRPOS: 83 | break; 84 | case ZRINIT: 85 | return OK; 86 | case ZCAN: 87 | default: 88 | return NERROR; 89 | } 90 | /* 91 | * If the reverse channel can be tested for data, 92 | * this logic may be used to detect error packets 93 | * sent by the receiver, in place of setjmp/longjmp 94 | * minprdy() returns non 0 if a character is available 95 | */ 96 | while (minprdy()) { 97 | if (QuitFlag) { 98 | return NERROR; 99 | } 100 | switch (readline(1)) { 101 | case CTRLC: 102 | case CAN: 103 | case ZPAD: 104 | goto rxint; 105 | case XOFF: /* Wait a while for an XON */ 106 | case XOFF|0200: 107 | readline(100); 108 | } 109 | } 110 | } 111 | 112 | if (setjmp(jb_stop)) { /* rx interrupt */ 113 | c = getinsync(1); 114 | if (c == ZACK) { 115 | goto gotanother; 116 | } 117 | purgeline(); 118 | /* zcrce - dinna wanna starta ping-pong game */ 119 | zsdata(Txbuf, 0, ZCRCE); 120 | goto gotack; 121 | } 122 | 123 | newcnt = Rxbuflen; 124 | Txwcnt = 0; 125 | stohdr(Txpos); 126 | zsbhdr(ZDATA, Txhdr); 127 | do { 128 | if (QuitFlag) { 129 | return NERROR; 130 | } 131 | if (Dontread) { 132 | n = Lastn; 133 | } else { 134 | n = filbuf(Txbuf, Blklen); 135 | Lastread = Txpos; 136 | Lastn = n; 137 | } 138 | Dontread = FALSE; 139 | if (n < Blklen) { 140 | e = ZCRCE; 141 | } else if (junkcount > 3) { 142 | e = ZCRCW; 143 | } else if (Bytcnt == Lastsync) { 144 | e = ZCRCW; 145 | } else if (Rxbuflen && (newcnt -= n) <= 0) { 146 | e = ZCRCW; 147 | } else if (Txwindow && (Txwcnt += n) >= Txwspac) { 148 | Txwcnt = 0; 149 | e = ZCRCQ; 150 | } else { 151 | e = ZCRCG; 152 | } 153 | zsdata(Txbuf, n, e); 154 | Txpos += (long)n; 155 | Bytcnt = Txpos; 156 | crcrept(Crc32t); /* praps report crc mode */ 157 | lreport(KBYTES,Bytcnt); 158 | if (e == ZCRCW) { 159 | goto waitack; 160 | } 161 | 162 | /* 163 | * If the reverse channel can be tested for data, 164 | * this logic may be used to detect error packets 165 | * sent by the receiver, in place of setjmp/longjmp 166 | * minprdy() returns non 0 if a character is available 167 | */ 168 | 169 | while (minprdy()) { 170 | if (QuitFlag) { 171 | return NERROR; 172 | } 173 | switch (readline(1)) { 174 | case CAN: 175 | case CTRLC: 176 | case ZPAD: 177 | c = getinsync(1); 178 | if (c == ZACK) { 179 | break; 180 | } 181 | purgeline(); 182 | /* zcrce - dinna wanna starta ping-pong game */ 183 | zsdata(Txbuf, 0, ZCRCE); 184 | goto gotack; 185 | case XOFF: /* Wait a while for an XON */ 186 | case XOFF|0200: 187 | readline(100); 188 | default: 189 | ++junkcount; 190 | 191 | } 192 | gotanother:; 193 | } 194 | if (Txwindow) { 195 | while ((tcount = Txpos - Lrxpos) >= Txwindow) { 196 | if (QuitFlag) { 197 | return NERROR; 198 | } 199 | if (e != ZCRCQ) { 200 | zsdata(Txbuf, 0, e = ZCRCQ); 201 | } 202 | c = getinsync(1); 203 | if (c != ZACK) { 204 | purgeline(); 205 | zsdata(Txbuf, 0, ZCRCE); 206 | goto gotack; 207 | } 208 | } 209 | } 210 | } while (n == Blklen); 211 | 212 | for (;;) { 213 | if (QuitFlag) { 214 | return NERROR; 215 | } 216 | stohdr(Txpos); 217 | zsbhdr(ZEOF, Txhdr); 218 | switch (getinsync(0)) { 219 | case ZACK: 220 | continue; 221 | case ZRPOS: 222 | goto somemore; 223 | case ZRINIT: 224 | return OK; 225 | case ZSKIP: 226 | return c; 227 | default: 228 | return NERROR; 229 | } 230 | } 231 | } 232 | 233 | /************************** END OF MODULE 7A *********************************/ 234 |  -------------------------------------------------------------------------------- /src/zmxfer3e.c: -------------------------------------------------------------------------------- 1 | /************************* START OF XFER MODULE 3 ***************************/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include "zmp.h" 7 | #include "zmodmdef.h" 8 | 9 | extern int opabort(); 10 | extern int zgethdr(char *,int); 11 | extern void zperr(char *,int); 12 | extern void clrline(int); 13 | 14 | extern char Rxhdr[4]; 15 | extern char Txhdr[4]; 16 | extern int Beenhereb4; 17 | extern long Rxpos; 18 | extern long Txpos; 19 | extern long Lrxpos; 20 | extern long Bytcnt; 21 | extern long Lastsync; 22 | extern long Lastread; 23 | extern int Incnt; 24 | extern int Fd; 25 | extern int Dontread; 26 | extern int Lastn; 27 | extern char *frametypes[]; 28 | 29 | /* 30 | * Respond to receiver's complaint, get back in sync with receiver 31 | */ 32 | int getinsync(flag) /* flag means that there was an error */ 33 | int flag; 34 | { 35 | static int c; 36 | unsigned u; 37 | 38 | for (;;) { 39 | if (opabort()) { 40 | return NERROR; 41 | } 42 | c = zgethdr(Rxhdr, 0); 43 | c = c < FRTYPES ? c : FRTYPES-1; 44 | sprintf(Buf,"Got %s", frametypes[c+FTOFFSET]); 45 | zperr(Buf,flag); 46 | switch (c) { 47 | 48 | case ZCAN: 49 | case ZABORT: 50 | case ZFIN: 51 | case TIMEOUT: 52 | return NERROR; 53 | 54 | case ZRPOS: 55 | /* ************************************* */ 56 | /* If sending to a modem buffer, you */ 57 | /* might send a break at this point to */ 58 | /* dump the modem's buffer. */ 59 | /* ************************************* */ 60 | if (Lastn >= 0 && Lastread == Rxpos) { 61 | Dontread = TRUE; 62 | } else { 63 | u = lseek(Fd, Rxpos, 0); /* absolute offset */ 64 | clrline(KBYTES); 65 | Incnt = 0; 66 | } 67 | Bytcnt = Lrxpos = Txpos = Rxpos; 68 | if (Lastsync == Rxpos) { 69 | if (++Beenhereb4 > 4) { 70 | if (Blklen > 256) { 71 | Blklen /= 2; 72 | } 73 | } 74 | } 75 | Lastsync = Rxpos; 76 | return c; 77 | 78 | case ZACK: 79 | Lrxpos = Rxpos; 80 | if (flag || Txpos == Rxpos) { 81 | return ZACK; 82 | } 83 | continue; 84 | 85 | case ZRINIT: 86 | case ZSKIP: 87 | return c; 88 | 89 | case NERROR: 90 | default: 91 | zsbhdr(ZNAK, Txhdr); 92 | continue; 93 | } 94 | } 95 | } 96 | 97 | /************************** END OF MODULE 7A *********************************/ 98 |  -------------------------------------------------------------------------------- /src/zmxfer3f.c: -------------------------------------------------------------------------------- 1 | /************************* START OF XFER MODULE 3 ***************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | #include "zmodmdef.h" 7 | 8 | extern void stohdr(long); 9 | extern void zshhdr(int,char *); 10 | extern void mcharout(char); 11 | 12 | extern char Txhdr[4]; 13 | extern char Rxhdr[4]; 14 | 15 | /* Say "bibi" to the receiver, try to do it cleanly */ 16 | 17 | void saybibi() 18 | { 19 | for (;;) { 20 | stohdr(0L); /* CAF Was zsbhdr - minor change */ 21 | zshhdr(ZFIN, Txhdr); /* to make debugging easier */ 22 | switch (zgethdr(Rxhdr, 0)) { 23 | case ZFIN: 24 | mcharout('O'); 25 | mcharout('O'); 26 | case ZCAN: 27 | case TIMEOUT: 28 | return; 29 | } 30 | } 31 | } 32 | 33 | /************************** END OF MODULE 7A *********************************/ 34 |  -------------------------------------------------------------------------------- /src/zmxfer3g.c: -------------------------------------------------------------------------------- 1 | /************************* START OF XFER MODULE 3 ***************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | #include "zmodmdef.h" 7 | 8 | extern int Zmodem; 9 | extern int Baudrate; 10 | 11 | char *ttime(fsize) 12 | long fsize; 13 | { 14 | static unsigned efficiency, cps, seconds; 15 | static char buffer[10]; 16 | 17 | efficiency = Zmodem ? 9 : 8; 18 | cps = (Baudrate/10) * efficiency; 19 | seconds = (unsigned)(fsize/cps); 20 | sprintf(buffer,"%u:%02u",seconds/60,seconds%60); 21 | return buffer; 22 | } 23 | 24 | /************************** END OF MODULE 7A *********************************/ 25 |  -------------------------------------------------------------------------------- /src/zmxfer3h.c: -------------------------------------------------------------------------------- 1 | /************************* START OF XFER MODULE 3 ***************************/ 2 | 3 | #include 4 | #include 5 | 6 | extern int Fd; 7 | 8 | void tfclose() /* close file if still open */ 9 | { 10 | if (Fd >= 0) { 11 | close(Fd); 12 | } 13 | Fd = -1; 14 | } 15 | 16 | /************************** END OF MODULE 7A *********************************/ 17 |  -------------------------------------------------------------------------------- /src/zmxfer3i.c: -------------------------------------------------------------------------------- 1 | /************************* START OF XFER MODULE 3 ***************************/ 2 | 3 | #include 4 | 5 | extern void putlabel(char *); 6 | 7 | extern char Buf[128]; 8 | 9 | void slabel() /*print send mode labels on the 25th line*/ 10 | { 11 | sprintf(Buf,"SEND FILE Mode: Press ESC to Abort..."); 12 | putlabel(Buf); 13 | } 14 | 15 | /************************** END OF MODULE 7A *********************************/ 16 |  -------------------------------------------------------------------------------- /src/zmxfer4.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/src/zmxfer4.com -------------------------------------------------------------------------------- /src/zmxfer4a.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 4 ******************************/ 2 | 3 | /* rz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "zmp.h" 9 | #include "zmodmdef.h" 10 | 11 | extern int wcrx(); 12 | extern int procheader(char *); 13 | extern int wcrxpn(char *); 14 | extern int opabort(); 15 | extern int rzmfile(); 16 | extern char *grabmem(unsigned *); 17 | extern char *alloc(int); 18 | extern int allocerror(void *); 19 | extern void rlabel(); 20 | extern void hidecurs(); 21 | extern void savecurs(); 22 | extern void showcurs(); 23 | extern void restcurs(); 24 | extern int openerror(int,char *,int); 25 | extern int tryz(); 26 | 27 | extern int Fd; 28 | extern int Errors; 29 | extern int Zctlesc; 30 | extern int Baudrate; 31 | extern int Tryzhdrtype; 32 | extern char *Secbuf; 33 | extern char *Cpmbuf; 34 | extern unsigned Cpbufsize; 35 | extern unsigned Cpindex; 36 | extern char *Rxptr; 37 | extern int Rxtimeout; 38 | 39 | int Wcsmask = 0377; 40 | 41 | int wcreceive(filename) 42 | char *filename; 43 | { 44 | static int c; 45 | 46 | rlabel(); 47 | QuitFlag = FALSE; 48 | Zctlesc = 0; 49 | Baudrate = Baudtable[Current.cbaudindex]; 50 | Tryzhdrtype = ZRINIT; 51 | Secbuf = alloc(KSIZE + 1); 52 | if (allocerror(Secbuf)) { 53 | return NERROR; 54 | } 55 | Cpmbuf = grabmem(&Cpbufsize); 56 | if (allocerror(Cpmbuf)) { 57 | return NERROR; 58 | } 59 | Cpindex = 0; /* just in case */ 60 | Rxptr = Cpmbuf; /* ditto */ 61 | Rxtimeout = 100; /* 10 seconds */ 62 | Errors = 0; 63 | 64 | #ifdef DEBUG 65 | printf("\nbuffer size = %u\n",Cpbufsize); 66 | wait(5); 67 | #endif 68 | 69 | savecurs(); 70 | hidecurs(); 71 | box(); 72 | if (filename == (char *) 0) {/* batch transfer */ 73 | Crcflag=(Wcsmask==0377); 74 | if (c=tryz()) { /* zmodem transfer */ 75 | report(PROTOCOL,"ZMODEM Receive"); 76 | if (c == ZCOMPL) { 77 | goto good; 78 | } 79 | if (c == NERROR) { 80 | goto fubar; 81 | } 82 | c = rzmfile(); 83 | if (c) { 84 | goto fubar; 85 | } 86 | } else { /* ymodem batch transfer */ 87 | report(PROTOCOL,"YMODEM Receive"); 88 | report(BLKCHECK,Crcflag?"CRC":"Checksum"); 89 | for (;;) { 90 | if (opabort()) { 91 | goto fubar; 92 | } 93 | if (wcrxpn(Secbuf)== NERROR) { 94 | goto fubar; 95 | } 96 | if (Secbuf[0]==0) { 97 | goto good; 98 | } 99 | if (procheader(Secbuf) == NERROR) { 100 | goto fubar; 101 | } 102 | if (wcrx()==NERROR) { 103 | goto fubar; 104 | } 105 | } 106 | } 107 | } else { 108 | report(PROTOCOL,"XMODEM Receive"); 109 | strcpy(Pathname,filename); 110 | checkpath(Pathname); 111 | 112 | testexist(Pathname); 113 | Fd = creat(Pathname, 0); 114 | if (openerror(Fd,Pathname,UBIOT)) { 115 | goto fubar1; 116 | } 117 | if (wcrx()==NERROR) { /* xmodem */ 118 | goto fubar; 119 | } 120 | } 121 | good: 122 | free(Cpmbuf); 123 | free(Secbuf); 124 | showcurs(); 125 | restcurs(); 126 | return OK; 127 | 128 | fubar: 129 | canit(); 130 | if (Fd >= 0) { 131 | closeit(); 132 | unlink(Pathname); /* File incomplete: erase it */ 133 | } 134 | fubar1: 135 | free(Cpmbuf); 136 | free(Secbuf); 137 | showcurs(); 138 | restcurs(); 139 | return NERROR; 140 | } 141 | /************************** END OF MODULE 8 *********************************/ 142 |  -------------------------------------------------------------------------------- /src/zmxfer4b.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 4 ******************************/ 2 | 3 | /* rz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include "zmp.h" 8 | #include "zmodmdef.h" 9 | 10 | extern void purgeline(); 11 | extern void mcharout(char); 12 | extern int wcgetsec(char *,int); 13 | extern int readline(int); 14 | 15 | extern int Firstsec; 16 | /* 17 | * Fetch a pathname from the other end as a C ctyle ASCIZ string. 18 | * Length is indeterminate as long as less than Blklen 19 | * A null string represents no more files (YMODEM) 20 | */ 21 | 22 | int wcrxpn(rpn) 23 | char *rpn; /* receive a pathname */ 24 | { 25 | static int c; 26 | 27 | purgeline(); 28 | 29 | et_tu: 30 | Firstsec=TRUE; 31 | mcharout(Crcflag?WANTCRC:NAK); 32 | while ((c = wcgetsec(rpn, 100)) != 0) { 33 | if (QuitFlag) 34 | return NERROR; 35 | if (c == WCEOT) { 36 | mcharout(ACK); 37 | readline(INTRATIME); 38 | goto et_tu; 39 | } 40 | return NERROR; 41 | } 42 | mcharout(ACK); 43 | return OK; 44 | } 45 | 46 | /************************** END OF MODULE 8 *********************************/ 47 |  -------------------------------------------------------------------------------- /src/zmxfer4c.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 4 ******************************/ 2 | 3 | /* rz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include "zmp.h" 8 | #include "zmodmdef.h" 9 | 10 | extern void report(int,char *); 11 | extern int opabort(); 12 | extern void mcharout(char); 13 | extern int wcgetsec(char *,int); 14 | extern int putsec(int,int); 15 | extern void sreport(int,long); 16 | extern void zperr(char *,int); 17 | extern int closeit(); 18 | extern void setmodtime(); 19 | 20 | extern int Firstsec; 21 | extern int Crcflag; 22 | extern char *Rxptr; 23 | extern int Wcsmask; 24 | 25 | /* 26 | * Adapted from CMODEM13.C, written by 27 | * Jack M. Wierda and Roderick W. Hart 28 | */ 29 | 30 | int wcrx() 31 | { 32 | static int sectnum, sectcurr; 33 | static char sendchar; 34 | static int cblklen; /* bytes to dump this block */ 35 | long charsgot; 36 | 37 | Firstsec=TRUE; 38 | sectnum=0; 39 | charsgot = 0L; 40 | sendchar=Crcflag?WANTCRC:NAK; 41 | report(BLKCHECK,Crcflag?"CRC":"Checksum"); 42 | 43 | for (;;) { 44 | if (opabort()) { 45 | return NERROR; 46 | } 47 | mcharout(sendchar); /* send it now, we're ready! */ 48 | sectcurr = wcgetsec(Rxptr,Firstsec||(sectnum&0177)?50:130); 49 | if (sectcurr==(sectnum+1 &Wcsmask)) { 50 | charsgot += Blklen; 51 | sreport(++sectnum,charsgot); 52 | cblklen = Blklen; 53 | if (putsec(cblklen,FALSE)==NERROR) { 54 | return NERROR; 55 | } 56 | sendchar=ACK; 57 | } else if (sectcurr==(sectnum&Wcsmask)) { 58 | zperr("Duplicate Sector",TRUE); 59 | sendchar=ACK; 60 | } else if (sectcurr==WCEOT) { 61 | if (closeit()) { 62 | return NERROR; 63 | } else { 64 | setmodtime(); 65 | } 66 | mcharout(ACK); 67 | return OK; 68 | } else if (sectcurr==NERROR) { 69 | return NERROR; 70 | } else { 71 | zperr( "Sync Error",TRUE); 72 | return NERROR; 73 | } 74 | } 75 | } 76 | 77 | /************************** END OF MODULE 8 *********************************/ 78 |  -------------------------------------------------------------------------------- /src/zmxfer4d.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 4 ******************************/ 2 | 3 | /* rz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include "zmp.h" 8 | #include "zmodmdef.h" 9 | 10 | extern int opabort(); 11 | extern int readline(int); 12 | extern unsigned updcrc(unsigned,unsigned); 13 | extern void zperr(char *,int); 14 | 15 | extern int Errors; 16 | extern int Xmodem; 17 | extern int Lastrx; 18 | extern int Firstsec; 19 | 20 | /* 21 | * Wcgetsec fetches a Ward Christensen type sector. 22 | * Returns sector number encountered or NERROR if valid sector not received, 23 | * or CAN CAN received 24 | * or WCEOT if eot sector 25 | * time is timeout for first char, set to 4 seconds thereafter 26 | ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK ************** 27 | * (Caller must do that when he is good and ready to get next sector) 28 | */ 29 | 30 | int wcgetsec(rxbuf, maxtime) 31 | char *rxbuf; 32 | int maxtime; 33 | { 34 | static int checksum, wcj, firstch; 35 | static unsigned oldcrc; 36 | static char *p; 37 | static int sectcurr; 38 | 39 | for (Lastrx=Errors=0; Errors < RETRYMAX; ) { /* errors incr by zperr */ 40 | if (opabort()) { 41 | return NERROR; 42 | } 43 | if ((firstch=readline(maxtime))==STX) { 44 | Blklen=KSIZE; 45 | goto get2; 46 | } 47 | if (firstch==SOH) { 48 | Blklen=SECSIZ; 49 | get2: 50 | sectcurr=readline(INTRATIME); 51 | if ((sectcurr+readline(INTRATIME))==0xFF) { 52 | oldcrc=checksum=0; 53 | for (p=rxbuf,wcj=Blklen; --wcj>=0; ) { 54 | if ((firstch=readline(INTRATIME)) < 0) { 55 | goto bilge; 56 | } 57 | oldcrc=updcrc(firstch, oldcrc); 58 | checksum += (*p++ = firstch); 59 | } 60 | if ((firstch=readline(INTRATIME)) < 0) { 61 | goto bilge; 62 | } 63 | if (Crcflag) { 64 | oldcrc=updcrc(firstch, oldcrc); 65 | if ((firstch=readline(INTRATIME)) < 0) { 66 | goto bilge; 67 | } 68 | oldcrc=updcrc(firstch, oldcrc); 69 | if (oldcrc & 0xFFFF) { 70 | zperr( "CRC Error",TRUE); 71 | } else { 72 | Firstsec=FALSE; 73 | return sectcurr; 74 | } 75 | } else if (((checksum-firstch)&0xFF)==0) { 76 | Firstsec=FALSE; 77 | return sectcurr; 78 | } else { 79 | zperr("Checksum error",TRUE); 80 | } 81 | } else { 82 | zperr("Block nr garbled",TRUE); 83 | } 84 | } else if (firstch==EOT && readline(10)==TIMEOUT) { 85 | /* make sure eot really is eot and not just mixmash */ 86 | return WCEOT; 87 | } else if (firstch==CAN) { 88 | if (Lastrx==CAN) { 89 | zperr( "Sender CANcelled",TRUE); 90 | return NERROR; 91 | } else { 92 | Lastrx=CAN; 93 | continue; 94 | } 95 | } else if (firstch==TIMEOUT) { 96 | if (Firstsec) { 97 | zperr( "TIMEOUT",TRUE); 98 | goto humbug; 99 | } 100 | bilge: 101 | zperr( "TIMEOUT",TRUE); 102 | } else if (firstch==0x0D && Firstsec) { 103 | continue; 104 | } else { 105 | zperr( "Bad header",TRUE); 106 | } 107 | 108 | humbug: 109 | Lastrx=0; 110 | while(readline(50) != TIMEOUT) 111 | if (QuitFlag) { 112 | return NERROR; 113 | } 114 | if (Firstsec) { 115 | if (Xmodem && (Errors == RETRYMAX/2)) { 116 | Crcflag = !Crcflag; 117 | } 118 | report(BLKCHECK,Crcflag?"CRC":"Checksum"); 119 | mcharout(Crcflag?WANTCRC:NAK); 120 | } else { 121 | maxtime=40; 122 | mcharout(NAK); 123 | } 124 | } 125 | /* try to stop the bubble machine. */ 126 | canit(); 127 | return NERROR; 128 | } 129 | 130 | /************************** END OF MODULE 8 *********************************/ 131 |  -------------------------------------------------------------------------------- /src/zmxfer4e.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 4 ******************************/ 2 | 3 | /* rz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "zmp.h" 11 | #include "zmodmdef.h" 12 | 13 | extern int openerror(int,char *,int); 14 | extern void clrreports(); 15 | extern void report(int,char *); 16 | extern char *ttime(long); 17 | extern void checkpath(char *); 18 | extern void testexist(char *); 19 | extern void zperr(char *,int); 20 | 21 | extern int Fd; 22 | 23 | /* 24 | * Process incoming file information header 25 | */ 26 | int procheader(name) 27 | char *name; 28 | { 29 | static char *p, *ap, c; 30 | 31 | /* 32 | * Process YMODEM,ZMODEM remote file management requests 33 | */ 34 | 35 | clrreports(); 36 | p = name + 1 + strlen(name); 37 | FileModTime = 0; 38 | if (*p) { /* file coming from Unix or DOS system */ 39 | ap = p; 40 | while ((c = *p) && (c != ' ')) /* find first space or null */ 41 | ++p; 42 | if (c) 43 | *p = '\0'; 44 | /* ap now points to a long integer in ascii */ 45 | report(FILESIZE,ap); 46 | report(SENDTIME,ttime(atol(ap))); 47 | while (*ap && *ap != ' ') { /* skip over filesize */ 48 | ++ap; 49 | } 50 | ++ap; /* if *ap is non zero, ap is pointing at the file mod timestamp */ 51 | if( *ap ) { 52 | while (*ap >= '0' && *ap <= '7') { 53 | FileModTime <<= 3; 54 | FileModTime += *ap -'0'; 55 | ++ap; 56 | } 57 | } 58 | } 59 | 60 | strcpy(Pathname, name); 61 | checkpath(Pathname); 62 | 63 | testexist(Pathname); 64 | Fd = creat(Pathname, 0); 65 | if (openerror(Fd,Pathname,UBIOT)) 66 | return NERROR; 67 | return OK; 68 | } 69 | 70 | /************************** END OF MODULE 8 *********************************/ 71 |  -------------------------------------------------------------------------------- /src/zmxfer4f.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 4 ******************************/ 2 | 3 | /* rz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | #include 7 | #include "zmp.h" 8 | 9 | extern void mstrout(char *,int); 10 | extern void purgeline(); 11 | 12 | /* send cancel string to get the other end to shut up */ 13 | void canit() 14 | { 15 | static char canistr[] = { 16 | 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 17 | }; 18 | 19 | mstrout(canistr,FALSE); 20 | purgeline(); 21 | } 22 | 23 | /************************** END OF MODULE 8 *********************************/ 24 |  -------------------------------------------------------------------------------- /src/zmxfer4g.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 4 ******************************/ 2 | 3 | /* rz.c By Chuck Forsberg modified for cp/m by Hal Maney */ 4 | 5 | #include 6 | 7 | extern void clrline(int); 8 | 9 | clrreports() 10 | { 11 | static int i; 12 | 13 | for (i=4; i<13; i++) 14 | clrline(i); 15 | } 16 | /************************** END OF MODULE 8 *********************************/ 17 |  -------------------------------------------------------------------------------- /src/zmxfer5.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/zmp/9c08e22787ad222fe140b63516537247d95ce063/src/zmxfer5.com -------------------------------------------------------------------------------- /src/zmxfer5a.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | 7 | extern void clrline(int); 8 | extern void report(int,char *); 9 | extern void dreport(int,int); 10 | 11 | extern int Errors; 12 | 13 | void zperr(string,incrflag) 14 | char *string; 15 | int incrflag; 16 | { 17 | clrline(MESSAGE); 18 | report(MESSAGE,string); 19 | if (incrflag) { 20 | dreport(ERRORS,++Errors); 21 | } 22 | } 23 | 24 | /************************** END OF MODULE 5 *********************************/ 25 |  -------------------------------------------------------------------------------- /src/zmxfer5b.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | 5 | extern void report(int,char *); 6 | extern char *itoa(int,char *); 7 | 8 | void dreport(row,value) 9 | int row, value; 10 | { 11 | static char buf[7]; 12 | 13 | report(row,itoa(value,buf)); 14 | } 15 | 16 | /************************** END OF MODULE 5 *********************************/ 17 |  -------------------------------------------------------------------------------- /src/zmxfer5c.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | 5 | extern void report(int,char *); 6 | extern char *ltoa(long,char *); 7 | 8 | void lreport(row,value) 9 | int row; 10 | long value; 11 | { 12 | static char buf[20]; 13 | 14 | report(row,ltoa(value,buf)); 15 | } 16 | 17 | /************************** END OF MODULE 5 *********************************/ 18 |  -------------------------------------------------------------------------------- /src/zmxfer5d.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | 7 | extern void dreport(int,int); 8 | extern void lreport(int,long); 9 | 10 | void sreport(sct,bytes) 11 | int sct; 12 | long bytes; 13 | { 14 | dreport(BLOCKS,sct); 15 | lreport(KBYTES,bytes); 16 | } 17 | 18 | /************************** END OF MODULE 5 *********************************/ 19 |  -------------------------------------------------------------------------------- /src/zmxfer5e.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | 5 | extern void report(int,char *); 6 | 7 | void clrline(line) 8 | int line; 9 | { 10 | report(line," "); 11 | } 12 | 13 | /************************** END OF MODULE 5 *********************************/ 14 |  -------------------------------------------------------------------------------- /src/zmxfer5f.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include "zmp.h" 7 | #include "zmodmdef.h" 8 | 9 | extern int opabort(); 10 | extern void stohdr(long); 11 | extern void zshhdr(int,char *); 12 | extern int zgethdr(char *,int); 13 | extern int zrdata(char *,int); 14 | extern void purgeline(); 15 | extern void zperr(char *,int); 16 | extern void ackbibi(); 17 | 18 | extern char Rxhdr[4]; 19 | extern char Txhdr[4]; 20 | extern char *Secbuf; 21 | extern int Errors; 22 | extern char Attn[ZATTNLEN+1]; 23 | extern int Tryzhdrtype; 24 | extern unsigned Cpbufsize; 25 | extern int Zctlesc; 26 | 27 | /* 28 | * Initialize for Zmodem receive attempt, try to activate Zmodem sender 29 | * Handles ZSINIT frame 30 | * Return ZFILE if Zmodem filename received, -1 on error, 31 | * ZCOMPL if transaction finished, else 0 32 | */ 33 | int tryz() 34 | { 35 | static int c, n, *ip; 36 | static int cmdzack1flg; 37 | 38 | if (Nozmodem) { /* ymodem has been forced */ 39 | return 0; 40 | } 41 | 42 | for (n=Zmodem?15:5; --n>=0; ) { 43 | if (opabort()) { 44 | return NERROR; 45 | } 46 | /* Set buffer length (0) and capability flags */ 47 | stohdr(0L); 48 | Txhdr[ZF0] = (Wantfcs32 ? CANFC32 : 0) | CANFDX; 49 | if (Zctlesc) { 50 | Txhdr[ZF0] |= TESCCTL; 51 | } 52 | ip = (int *)&Txhdr[ZP0]; 53 | *ip = Cpbufsize; 54 | zshhdr(Tryzhdrtype, Txhdr); 55 | if (Tryzhdrtype == ZSKIP) { /* Don't skip too far */ 56 | Tryzhdrtype = ZRINIT; /* CAF 8-21-87 */ 57 | } 58 | again: 59 | switch (zgethdr(Rxhdr, 0)) { 60 | case ZRQINIT: 61 | continue; 62 | case ZEOF: 63 | continue; 64 | case TIMEOUT: 65 | continue; 66 | case ZFILE: 67 | Tryzhdrtype = ZRINIT; 68 | c = zrdata(Secbuf, KSIZE); 69 | if (c == GOTCRCW) { 70 | return ZFILE; 71 | } 72 | zshhdr(ZNAK, Txhdr); 73 | goto again; 74 | case ZSINIT: 75 | Zctlesc = TESCCTL & Rxhdr[ZF0]; 76 | if (zrdata(Attn, ZATTNLEN) == GOTCRCW) { 77 | zshhdr(ZACK, Txhdr); 78 | goto again; 79 | } 80 | zshhdr(ZNAK, Txhdr); 81 | goto again; 82 | case ZFREECNT: 83 | stohdr(0L); 84 | zshhdr(ZACK, Txhdr); 85 | goto again; 86 | case ZCOMMAND: 87 | cmdzack1flg = Rxhdr[ZF0]; 88 | if (zrdata(Secbuf, KSIZE) == GOTCRCW) { 89 | stohdr(0L); 90 | purgeline(); /* dump impatient questions */ 91 | do { 92 | zshhdr(ZCOMPL, Txhdr); 93 | zperr("Waiting for ZFIN",FALSE); 94 | if (opabort()) { 95 | return NERROR; 96 | } 97 | } while (++Errors<20 && zgethdr(Rxhdr,1) != ZFIN); 98 | ackbibi(); 99 | return ZCOMPL; 100 | } 101 | zshhdr(ZNAK, Txhdr); 102 | goto again; 103 | case ZCOMPL: 104 | goto again; 105 | default: 106 | continue; 107 | case ZFIN: 108 | ackbibi(); 109 | return ZCOMPL; 110 | case ZCAN: 111 | return NERROR; 112 | } 113 | } 114 | return 0; 115 | } 116 | 117 | /************************** END OF MODULE 5 *********************************/ 118 |  -------------------------------------------------------------------------------- /src/zmxfer5g.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | #include "zmodmdef.h" 7 | 8 | extern int opabort(); 9 | extern int rzfile(); 10 | extern int tryz(); 11 | 12 | /* 13 | * Receive 1 or more files with ZMODEM protocol 14 | */ 15 | 16 | int rzmfile() 17 | { 18 | static int c; 19 | 20 | for (;;) { 21 | if (opabort()) { 22 | return NERROR; 23 | } 24 | c = rzfile(); 25 | closeit(); 26 | switch (c) { 27 | case ZEOF: 28 | case ZSKIP: 29 | switch (tryz()) { 30 | case ZCOMPL: 31 | return OK; 32 | default: 33 | return NERROR; 34 | case ZFILE: 35 | break; 36 | } 37 | continue; 38 | default: 39 | return c; 40 | case NERROR: 41 | return NERROR; 42 | } 43 | } 44 | } 45 | 46 | /************************** END OF MODULE 5 *********************************/ 47 |  -------------------------------------------------------------------------------- /src/zmxfer5h.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | #include "zmodmdef.h" 7 | 8 | extern void zperr(char *,int); 9 | extern int procheader(char *); 10 | extern int opabort(); 11 | extern void stohdr(long); 12 | extern void zshhdr(int,char *); 13 | extern int zgethdr(char *,int); 14 | extern int zrdata(char *,int); 15 | extern long rclhdr(char *); 16 | extern int closeit(); 17 | extern void crcrept(int); 18 | extern int zmputs(char *); 19 | extern void statrep(long); 20 | extern int putsec(int,int); 21 | extern void mcharout(char); 22 | extern void setmodtime(); 23 | 24 | extern int Tryzhdrtype; 25 | extern int Firstsec; 26 | extern char *Secbuf; 27 | extern int Errors; 28 | extern int Crc32; 29 | extern unsigned Cpindex; 30 | extern unsigned Cpbufsize; 31 | extern char *Rxptr; 32 | extern char Attn[ZATTNLEN+1]; 33 | extern int Rxcount; 34 | extern char Rxhdr[4]; 35 | extern char Txhdr[4]; 36 | 37 | #define MAX_ZERRORS 10 38 | /* 39 | * Receive a file with ZMODEM protocol 40 | * Assumes file name frame is in Secbuf 41 | */ 42 | int rzfile() 43 | { 44 | static int c, n; 45 | static unsigned bufleft; 46 | static long rxbytes; 47 | 48 | if (procheader(Secbuf) == NERROR) { 49 | return (Tryzhdrtype = ZSKIP); 50 | } 51 | 52 | n = MAX_ZERRORS; 53 | rxbytes = 0L; 54 | Firstsec = TRUE; 55 | 56 | for (;;) { 57 | if (opabort()) { 58 | return NERROR; 59 | } 60 | stohdr(rxbytes); 61 | zshhdr(ZRPOS, Txhdr); 62 | nxthdr: 63 | if (opabort()) { 64 | return NERROR; 65 | } 66 | switch (c = zgethdr(Rxhdr, 0)) { 67 | 68 | default: 69 | return NERROR; 70 | 71 | case ZNAK: 72 | case TIMEOUT: 73 | if ( --n < 0) { 74 | return NERROR; 75 | } 76 | 77 | case ZFILE: 78 | zrdata(Secbuf, KSIZE); 79 | continue; 80 | 81 | case ZEOF: 82 | if (rclhdr(Rxhdr) != rxbytes) { 83 | /* 84 | * Ignore eof if it's at wrong place - force 85 | * a timeout because the eof might have gone 86 | * out before we sent our zrpos. 87 | */ 88 | Errors = 0; 89 | goto nxthdr; 90 | } 91 | if (closeit()) { 92 | Tryzhdrtype = ZFERR; 93 | return NERROR; 94 | } else { 95 | setmodtime(); 96 | } 97 | lreport(KBYTES,rxbytes); 98 | crcrept(Crc32); 99 | return c; 100 | 101 | case NERROR: /* Too much garbage in header search error */ 102 | if ( --n < 0) { 103 | return NERROR; 104 | } 105 | zmputs(Attn); 106 | continue; 107 | 108 | case ZDATA: 109 | if (rclhdr(Rxhdr) != rxbytes) { 110 | if ( --n < 0) { 111 | return NERROR; 112 | } 113 | zmputs(Attn); 114 | continue; 115 | } 116 | moredata: 117 | if (opabort()) { 118 | return NERROR; 119 | } 120 | bufleft = Cpbufsize - Cpindex; 121 | c = zrdata(Rxptr, (bufleft > KSIZE) ? KSIZE : bufleft); 122 | switch (c) { 123 | 124 | case ZCAN: 125 | return NERROR; 126 | 127 | case NERROR: /* CRC error */ 128 | statrep(rxbytes); 129 | if ( --n < 0) { 130 | return NERROR; 131 | } 132 | zmputs(Attn); 133 | continue; 134 | 135 | case TIMEOUT: 136 | statrep(rxbytes); 137 | if ( --n < 0) { 138 | return NERROR; 139 | } 140 | continue; 141 | 142 | case GOTCRCW: 143 | n = MAX_ZERRORS; 144 | if (putsec(Rxcount,TRUE) == NERROR) { 145 | return NERROR; /* Write to disk! */ 146 | } 147 | rxbytes += Rxcount; 148 | stohdr(rxbytes); 149 | statrep(rxbytes); 150 | zshhdr(ZACK, Txhdr); 151 | mcharout(XON); 152 | goto nxthdr; 153 | 154 | case GOTCRCQ: 155 | n = MAX_ZERRORS; 156 | if (putsec(Rxcount,TRUE) == NERROR) { 157 | return NERROR; /* Write to disk! */ 158 | } 159 | rxbytes += Rxcount; 160 | stohdr(rxbytes); 161 | statrep(rxbytes); 162 | zshhdr(ZACK, Txhdr); 163 | goto moredata; 164 | 165 | case GOTCRCG: 166 | n = MAX_ZERRORS; 167 | if (putsec(Rxcount,FALSE) == NERROR) { 168 | return NERROR; /* Don't write to disk */ 169 | } 170 | rxbytes += Rxcount; 171 | goto moredata; 172 | 173 | case GOTCRCE: 174 | n = MAX_ZERRORS; 175 | if (putsec(Rxcount,FALSE) == NERROR) { 176 | return NERROR; /* Don't write to disk */ 177 | } 178 | rxbytes += Rxcount; 179 | goto nxthdr; 180 | } 181 | } 182 | } 183 | } 184 | 185 | /************************** END OF MODULE 5 *********************************/ 186 |  -------------------------------------------------------------------------------- /src/zmxfer5i.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | 7 | extern void lreport(int,long); 8 | extern void crcrept(int); 9 | 10 | extern int Crc32; 11 | 12 | /* Status report: don't do unless after error or ZCRCW since characters */ 13 | /* will be lost unless rx has interrupt-driven I/O */ 14 | void statrep(rxbytes) 15 | long rxbytes; 16 | { 17 | lreport(KBYTES,rxbytes); 18 | crcrept(Crc32); 19 | } 20 | 21 | /************************** END OF MODULE 5 *********************************/ 22 |  -------------------------------------------------------------------------------- /src/zmxfer5j.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | 7 | extern void report(int,char *); 8 | 9 | extern int Firstsec; 10 | 11 | /* Report CRC mode in use, but only if first sector */ 12 | void crcrept(flag) 13 | int flag; 14 | { 15 | if (Firstsec) 16 | report(BLKCHECK, flag ? "CRC-32" : "CRC-16"); 17 | Firstsec = FALSE; /* clear the flag */ 18 | } 19 | 20 | /************************** END OF MODULE 5 *********************************/ 21 |  -------------------------------------------------------------------------------- /src/zmxfer5k.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include "zmp.h" 7 | 8 | extern void zperr(char *,int); 9 | 10 | extern int Fd; 11 | extern char *Rxptr; 12 | extern char *Cpmbuf; 13 | extern unsigned Cpindex; 14 | extern unsigned Cpbufsize; 15 | 16 | /* Add a block to the main buffer pointer and write to disk if full */ 17 | /* or if flag set */ 18 | int putsec(count,flag) 19 | int count, flag; 20 | { 21 | short status; 22 | unsigned size; 23 | 24 | status = 0; 25 | Rxptr += count; 26 | Cpindex += count; 27 | if ((Cpindex >= Cpbufsize) || flag) 28 | { 29 | size = (Cpindex > Cpbufsize) ? Cpbufsize : Cpindex; 30 | 31 | status = write(Fd,Cpmbuf,size); 32 | if (status != size) 33 | { 34 | zperr("Disk write error",TRUE); 35 | status = NERROR; 36 | } 37 | Cpindex = 0; 38 | Rxptr = Cpmbuf; 39 | } 40 | return status; 41 | } 42 | 43 | /************************** END OF MODULE 5 *********************************/ 44 |  -------------------------------------------------------------------------------- /src/zmxfer5l.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include "zmp.h" 6 | 7 | extern int opabort(); 8 | extern void wait(int); 9 | extern void sendbrk(); 10 | extern void mcharout(char); 11 | 12 | /* 13 | * Send a string to the modem, processing for \336 (sleep 1 sec) 14 | * and \335 (break signal) 15 | */ 16 | int zmputs(s) 17 | char *s; 18 | { 19 | static int c; 20 | 21 | while (*s) { 22 | if (opabort()) 23 | return NERROR; 24 | switch (c = *s++) { 25 | case '\336': 26 | wait(1); 27 | continue; 28 | case '\335': 29 | sendbrk(); 30 | continue; 31 | default: 32 | mcharout(c); 33 | } 34 | } 35 | } 36 | 37 | /************************** END OF MODULE 5 *********************************/ 38 |  -------------------------------------------------------------------------------- /src/zmxfer5m.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "zmp.h" 8 | 9 | /* Test if file exists, rename to .BAK if so */ 10 | void testexist(filename) 11 | char *filename; 12 | { 13 | int fd; 14 | char *p, newfile[20], *index(); 15 | 16 | if ((fd = open(filename,0)) != UBIOT) { 17 | close(fd); 18 | strcpy(newfile,filename); 19 | if (p = index(newfile,'.')) 20 | *p = '\0'; /* stop at dot */ 21 | strcat(newfile,".bak"); 22 | unlink(newfile); /* remove any .bak already there */ 23 | rename(filename,newfile); 24 | } 25 | } 26 | 27 | /************************** END OF MODULE 5 *********************************/ 28 |  -------------------------------------------------------------------------------- /src/zmxfer5n.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include "zmp.h" 7 | 8 | extern void zperr(char *,int); 9 | extern int roundup(int,int); 10 | 11 | extern unsigned Cpindex; 12 | extern int Fd; 13 | extern char *Cpmbuf; 14 | extern char *Rxptr; 15 | 16 | /* 17 | * Close the receive dataset, return OK or NERROR 18 | */ 19 | int closeit() 20 | { 21 | static int status; 22 | int length, padding; 23 | 24 | status = OK; 25 | if (Fd != -1) { 26 | if (Cpindex) { 27 | length = 128*roundup(Cpindex,128); 28 | /* pad last sector with ^Z if necessary */ 29 | /* otherwise text files from Linux boxes */ 30 | /* don't end properly */ 31 | padding = length - Cpindex; 32 | while (padding > 0) { 33 | *Rxptr++ = CTRLZ; 34 | --padding; 35 | } 36 | 37 | status = ((write(Fd,Cpmbuf,length) == length) ? OK : NERROR); 38 | 39 | Cpindex = 0; 40 | Rxptr = Cpmbuf; 41 | } 42 | if (status == NERROR) { 43 | zperr("Disk write error",TRUE); 44 | } 45 | 46 | if (close(Fd)==NERROR) { 47 | Fd = -1; 48 | 49 | zperr("File close error",TRUE); 50 | return NERROR; 51 | } 52 | } 53 | return status; 54 | } 55 | 56 | /************************** END OF MODULE 5 *********************************/ 57 |  -------------------------------------------------------------------------------- /src/zmxfer5o.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "zmp.h" 9 | #include "zmodmdef.h" 10 | 11 | extern void stohdr(long); 12 | extern void purgeline(); 13 | extern zshhdr(int,char *); 14 | extern int readline(int); 15 | 16 | extern char Txhdr[4]; 17 | /* 18 | * Ack a ZFIN packet, let byegones be byegones 19 | */ 20 | 21 | void ackbibi() 22 | { 23 | static int n; 24 | 25 | stohdr(0L); 26 | for (n=3; --n>=0; ) { 27 | purgeline(); 28 | zshhdr(ZFIN, Txhdr); 29 | switch (readline(100)) { 30 | case 'O': 31 | readline(INTRATIME); /* Discard 2nd 'O' */ 32 | return; 33 | case RCDO: 34 | return; 35 | case TIMEOUT: 36 | default: 37 | break; 38 | } 39 | } 40 | } 41 | 42 | /************************** END OF MODULE 5 *********************************/ 43 |  -------------------------------------------------------------------------------- /src/zmxfer5p.c: -------------------------------------------------------------------------------- 1 | /********************** START OF XFER MODULE 5 ******************************/ 2 | 3 | #include 4 | 5 | extern void putlabel(char *); 6 | 7 | void rlabel() /*print receive mode labels on the 25th line*/ 8 | { 9 | putlabel("RECEIVE FILE Mode: Press ESC to Abort..."); 10 | } 11 | 12 | /************************** END OF MODULE 5 *********************************/ 13 |  -------------------------------------------------------------------------------- /src/ztcompil.cmd: -------------------------------------------------------------------------------- 1 | CC ZMTERM 2 | CC ZMTERM2 3 | CC ZMTERM3 4 | CC ZMTERM4 5 | LINK 5 | #include 6 | #include "zmp.h" 7 | #include "zmodmdef.h" 8 | 9 | #undef DEBUG 10 | 11 | extern long updc32(int,long); 12 | extern unsigned updcrc(unsigned,unsigned); 13 | extern void zperr(char *,int); 14 | extern int readline(int); 15 | extern void xmchout(char); 16 | 17 | int zdlread(); 18 | int zrb32hdr(char *); 19 | int zrhhdr(char *); 20 | int zgethex(); 21 | void zputhex(int); 22 | void zsendline(int); 23 | int zgeth1(); 24 | int noxrd7(); 25 | void stohdr(long); 26 | long rclhdr(char *); 27 | 28 | extern int Zctlesc; 29 | extern char Txhdr[4]; 30 | extern int Rxtimeout; 31 | extern int Rxtype; 32 | 33 | /* Receive a binary style header (type and position) */ 34 | int zrbhdr(hdr) 35 | char *hdr; 36 | { 37 | static int c, n; 38 | static unsigned crc; 39 | 40 | if ((c = zdlread()) & ~0377) { 41 | return c; 42 | } 43 | Rxtype = c; 44 | crc = updcrc(c, 0); 45 | 46 | for (n=4; --n >= 0; ++hdr) { 47 | if ((c = zdlread()) & ~0377) { 48 | return c; 49 | } 50 | crc = updcrc(c, crc); 51 | *hdr = c; 52 | } 53 | if ((c = zdlread()) & ~0377) { 54 | return c; 55 | } 56 | crc = updcrc(c, crc); 57 | if ((c = zdlread()) & ~0377) { 58 | return c; 59 | } 60 | crc = updcrc(c, crc); 61 | if (crc & 0xFFFF) { 62 | zperr("Bad Header CRC",TRUE); 63 | return NERROR; 64 | } 65 | Zmodem = 1; 66 | 67 | #ifdef DEBUG 68 | printf("\nReceived BINARY header type %d: ",Rxtype); 69 | for (n = -4; n < 0; n++) { 70 | prhex( *(hdr + n)); 71 | } 72 | printf("\n"); 73 | #endif 74 | 75 | return Rxtype; 76 | } 77 | 78 | /* Receive a binary style header (type and position) with 32 bit FCS */ 79 | int zrb32hdr(hdr) 80 | char *hdr; 81 | { 82 | static int c, n; 83 | static long crc; 84 | 85 | if ((c = zdlread()) & ~0377) { 86 | return c; 87 | } 88 | Rxtype = c; 89 | crc = 0xFFFFFFFFL; 90 | crc = updc32(c, crc); 91 | 92 | for (n=4; --n >= 0; ++hdr) { 93 | if ((c = zdlread()) & ~0377) { 94 | return c; 95 | } 96 | crc = updc32(c, crc); 97 | *hdr = c; 98 | } 99 | for (n=4; --n >= 0;) { 100 | if ((c = zdlread()) & ~0377) { 101 | return c; 102 | } 103 | crc = updc32(c, crc); 104 | } 105 | if (crc != 0xDEBB20E3) { 106 | zperr("Bad Header CRC",TRUE); 107 | return NERROR; 108 | } 109 | Zmodem = 1; 110 | 111 | #ifdef DEBUG 112 | printf("\nReceived 32-bit FCS BINARY header type %d: ",Rxtype); 113 | for (n = -4; n < 0; n++) 114 | prhex( *(hdr + n)); 115 | printf("\n"); 116 | #endif 117 | 118 | return Rxtype; 119 | } 120 | 121 | 122 | /* Receive a hex style header (type and position) */ 123 | int zrhhdr(hdr) 124 | char *hdr; 125 | { 126 | static int c; 127 | static unsigned crc; 128 | static int n; 129 | 130 | if ((c = zgethex()) < 0) { 131 | return c; 132 | } 133 | Rxtype = c; 134 | crc = updcrc(c, 0); 135 | 136 | for (n=4; --n >= 0; ++hdr) { 137 | if ((c = zgethex()) < 0) { 138 | return c; 139 | } 140 | crc = updcrc(c, crc); 141 | *hdr = c; 142 | } 143 | if ((c = zgethex()) < 0) { 144 | return c; 145 | } 146 | crc = updcrc(c, crc); 147 | if ((c = zgethex()) < 0) { 148 | return c; 149 | } 150 | crc = updcrc(c, crc); 151 | if (crc & 0xFFFF) { 152 | zperr("Bad Header CRC",TRUE); 153 | return NERROR; 154 | } 155 | if (readline(INTRATIME) == '\r') { /* Throw away possible cr/lf */ 156 | readline(INTRATIME); 157 | } 158 | Zmodem = 1; 159 | 160 | #ifdef DEBUG 161 | printf("\nReceived HEX header type %d: ",Rxtype); 162 | for (n = -4; n < 0; n++) { 163 | prhex( *(hdr + n)); 164 | } 165 | printf("\n"); 166 | #endif 167 | 168 | return Rxtype; 169 | } 170 | 171 | /* Send a byte as two hex digits */ 172 | void zputhex(c) 173 | int c; 174 | { 175 | static char digits[] = "0123456789abcdef"; 176 | 177 | xmchout(digits[(c&0xF0)>>4]); 178 | xmchout(digits[(c)&0xF]); 179 | } 180 | 181 | /* 182 | * Send character c with ZMODEM escape sequence encoding. 183 | * Escape XON, XOFF. Escape CR following @ (Telenet net escape) 184 | */ 185 | void zsendline(c) 186 | int c; 187 | { 188 | static lastsent; 189 | 190 | switch (c &= 0377) { 191 | case ZDLE: 192 | xmchout(ZDLE); 193 | xmchout (lastsent = (c ^= 0100)); 194 | break; 195 | case 015: 196 | case 0215: 197 | if (!Zctlesc && (lastsent & 0177) != '@') { 198 | goto sendit; 199 | } 200 | /* **** FALL THRU TO **** */ 201 | case 020: 202 | case 021: 203 | case 023: 204 | case 0220: 205 | case 0221: 206 | case 0223: 207 | xmchout(ZDLE); 208 | c ^= 0100; 209 | sendit: 210 | xmchout(lastsent = c); 211 | break; 212 | default: 213 | if (Zctlesc && ! (c & 0140)) { 214 | xmchout(ZDLE); 215 | c ^= 0100; 216 | } 217 | xmchout(lastsent = c); 218 | } 219 | } 220 | 221 | /* Decode two lower case hex digits into an 8 bit byte value */ 222 | int zgethex() 223 | { 224 | int c; 225 | 226 | c = zgeth1(); 227 | return c; 228 | } 229 | 230 | int zgeth1() 231 | { 232 | static int c, n; 233 | 234 | if ((c = noxrd7()) < 0) 235 | return c; 236 | n = c - '0'; 237 | if (n > 9) { 238 | n -= ('a' - ':'); 239 | } 240 | if (n & ~0xF) { 241 | return NERROR; 242 | } 243 | if ((c = noxrd7()) < 0) { 244 | return c; 245 | } 246 | c -= '0'; 247 | if (c > 9) { 248 | c -= ('a' - ':'); 249 | } 250 | if (c & ~0xF) { 251 | return NERROR; 252 | } 253 | c += (n<<4); 254 | return c; 255 | } 256 | 257 | /* 258 | * Read a byte, checking for ZMODEM escape encoding 259 | * including CAN*5 which represents a quick abort 260 | */ 261 | 262 | int zdlread() 263 | { 264 | static int c; 265 | 266 | again: 267 | switch (c = readline(Rxtimeout)) { 268 | case ZDLE: 269 | break; 270 | case 023: 271 | case 0223: 272 | case 021: 273 | case 0221: 274 | goto again; 275 | default: 276 | if (Zctlesc && !(c & 0140)) { 277 | goto again; 278 | } 279 | return c; 280 | } 281 | again2: 282 | if ((c = readline(Rxtimeout)) < 0) { 283 | return c; 284 | } 285 | if (c == CAN && (c = readline(Rxtimeout)) < 0) { 286 | return c; 287 | } 288 | if (c == CAN && (c = readline(Rxtimeout)) < 0) { 289 | return c; 290 | } 291 | if (c == CAN && (c = readline(Rxtimeout)) < 0) { 292 | return c; 293 | } 294 | switch (c) { 295 | case CAN: 296 | return GOTCAN; 297 | case ZCRCE: 298 | case ZCRCG: 299 | case ZCRCQ: 300 | case ZCRCW: 301 | return (c | GOTOR); 302 | case ZRUB0: 303 | return 0177; 304 | case ZRUB1: 305 | return 0377; 306 | case 023: 307 | case 0223: 308 | case 021: 309 | case 0221: 310 | goto again2; 311 | default: 312 | if (Zctlesc && ! (c & 0140)) { 313 | goto again2; 314 | } 315 | if ((c & 0140) == 0100) { 316 | return (c ^ 0100); 317 | } 318 | break; 319 | } 320 | sprintf(Buf,"Bad escape %x", c); 321 | zperr(Buf,TRUE); 322 | return NERROR; 323 | } 324 | 325 | /* 326 | * Read a character from the modem line with timeout. 327 | * Eat parity, XON and XOFF characters. 328 | */ 329 | int noxrd7() 330 | { 331 | static int c; 332 | 333 | for (;;) { 334 | if ((c = readline(Rxtimeout)) < 0) { 335 | return c; 336 | } 337 | switch (c &= 0177) { 338 | case XON: 339 | case XOFF: 340 | continue; 341 | default: 342 | if (Zctlesc && !(c & 0140)) { 343 | continue; 344 | } 345 | case '\r': 346 | case '\n': 347 | case ZDLE: 348 | return c; 349 | } 350 | } 351 | } 352 | 353 | /* Store long integer pos in Txhdr */ 354 | void stohdr(pos) 355 | long pos; 356 | { 357 | Txhdr[ZP0] = pos; 358 | Txhdr[ZP1] = (pos>>8); 359 | Txhdr[ZP2] = (pos>>16); 360 | Txhdr[ZP3] = (pos>>24); 361 | } 362 | 363 | /* Recover a long integer from a header */ 364 | long rclhdr(hdr) 365 | char *hdr; 366 | { 367 | static long l; 368 | 369 | l = (unsigned)(hdr[ZP3] & 0377); 370 | l = (l << 8) | (unsigned)(hdr[ZP2] & 0377); 371 | l = (l << 8) | (unsigned)(hdr[ZP1] & 0377); 372 | l = (l << 8) | (unsigned)(hdr[ZP0] & 0377); 373 | #ifdef DEBUG 374 | lreport(FBLOCKS,l); 375 | #endif 376 | return l; 377 | } 378 | 379 | /***************************** End of hzm2.c *********************************/ 380 |  --------------------------------------------------------------------------------