/*
 *  xprzmodem.h: Definitions for xprzmodem.library;
 *  Version 2.0, 28 October 1989, by Rick Huebner.
 *  Released to the Public Domain; do as you like with this code.
 */

/* #define DEBUGLOG 1 */

#define mysprintf sprintf

#include <proto/exec.h>
#include <devices/timer.h>

/* Return codes */
#define OK        0
#define ERROR   (-1)
#define TIMEOUT (-2)
#define RCDO    (-3)

/* Relevant control characters */
#define CR	('M' & 0x1F)	/* ^M */
#define DLE	('P' & 0x1F)	/* ^P */
#define XON	('Q' & 0x1F)	/* ^Q */
#define XOFF	('S' & 0x1F)	/* ^S */
#define CAN	('X' & 0x1F)	/* ^X */
#define CPMEOF	('Z' & 0x1F)	/* ^Z */

/* Misc. program constants */
#define LZMANAG		  0	/* Default ZMODEM file management mode */
#define LZTRANS		  0	/* Default ZMODEM file transport mode */
#define PATHLEN		256	/* What's the max legal path size? */
#define CONFIGLEN	 32	/* Max length of transfer options string */
#define KSIZE	       8192	/* Max allowable packet size */
#define MINBLOCK	 64	/* Min allowable packet size */
#define MAXGOODNEEDED  8192	/* Max # good bytes req'd to bump packet size */

/* Provision for future 7-bit ZMODEM; for now, there's no difference */
#define sendline xsendline

/*
 * Replacement for global variables normally used, in order to make code
 * fully reentrant; each invocation allocs their own Vars, and passes the
 * struct pointer down through the entire program so they're always available.
 * Pointer to this struct is usually able to be a register variable, so access
 * is no worse than any stack variable (all register-relative).  Kinda
 * kludgey, but the original ZModem code design depended on lots of globals,
 * and I didn't want to redesign the whole damn thing.  Besides, it's more
 * efficient than constantly pushing & popping args all over the place.
 */

struct Vars
{
   struct XPR_IO io;          /* Copy of XProto IO struct passed by term prog. */
   struct XPR_UPDATE __aligned xpru; /* Scratchpad xpr_update() control struct */
   struct timeval __aligned Starttime; /* Time transfer started */
   UBYTE __aligned Rxhdr [4]; /* Received header */
   UBYTE Txhdr [4];           /* Transmitted header */
   UBYTE Msgbuf [128];        /* Scratchpad buffer for printing messages */
   UBYTE Filename [PATHLEN];  /* Name of the file being up/downloaded */
   UBYTE Pktbuf [KSIZE];      /* File data packet buffer */
   UBYTE Modembuf [256];      /* Input buffer for data from modem */
   UBYTE Outbuf [KSIZE * 2 + 256]; /* Output buffer for data to modem */
   UBYTE *Modemchar;          /* Next char to get from Modembuf */
   long  File;                /* Handle of file being transferred */
   long  Baud;                /* BPS setting of modem */
   long  Strtpos;             /* Starting byte position of transfer */
   long  Fsize;               /* Size of file being transferred */
   long  Rxbytes;             /* Number of bytes received so far */
   long  Rxpos;               /* Received file position */
   long  Txpos;               /* Transmitted file position */
   short Filcnt;              /* Number of files opened for transmission */
   short Errcnt;              /* Number of files unreadable */
   short Noroom;              /* Flags 'insufficient disk space' errors */
   short Rxbuflen;            /* Largest frame they're willing to xfer */
   short Tframlen;            /* Largest frame we're willing to xfer */
   short Rxtimeout;           /* Tenths of seconds to wait for something */
   short Tryzhdrtype;         /* Header type to send corresp to Last rx close */
   short Modemcount;          /* Number of bytes available in Modembuf */
   short Outbuflen;           /* Number of bytes currently stored in Outbuf */
   short Rxframeind;          /* ZBIN or ZHEX; type of frame received */
   short Txfcs32;	      /* TRUE means send binary frame with 32 bit FCS */
   short Rxflags;	      /* Temp register */
   short Wantfcs32;	      /* want to send 32 bit FCS */
   short Crc32t;	      /* Display flag indicates 32 bit CRC being sent */
   short Crc32;		      /* Display flag indicates 32 bit CRC being recd */
   short Rxtype;              /* Type of header received */
   short Rxcount;             /* Count of data bytes received */
   short Znulls;              /* Number of nulls to send at begin of ZDATA hdr */
   short ErrorLimit;          /* How many sequential errors before abort */
   char  Rxbinary;            /* Force binary mode download? */
   char  Rxascii;             /* Force text mode download? */
   char  Thisbinary;          /* Receive this file in binary mode? */
   char  Lzconv;              /* Suggested binary/text mode for uploads */
   char  Eofseen;             /* Text-mode EOF marker (^Z) rec'd on download? */
   UBYTE Zconv;               /* ZMODEM file conversion request */
   UBYTE Zmanag;              /* ZMODEM file management request */
   UBYTE Ztrans;              /* ZMODEM file transport request */
   UBYTE Lastsent;            /* Last text char written by putsec() */
   UBYTE Lastzsent;           /* Last char sent by zsendline() */
   UBYTE Fileflush;           /* Flush file I/O buffer before closing? */
   UBYTE Attn[ZATTNLEN + 1];  /* Attention string rx sends to tx on err */
   };

/*
 * Option settings and other variables needed outside of XProtocolSend/Receive;
 * separated from rest of Vars so that huge Vars struct doesn't have to be
 * allocated except during transfers.  Pointer to this struct kept in xpr_data.
 */
struct SetupVars
{
   UBYTE *matchptr, *bufpos;
   short buflen;
   UBYTE option_t[2], option_o[2], option_b[8], option_f[8], option_e[8],
	 option_s[4];
   UBYTE option_r[4], option_a[4], option_d[4], option_k[4], option_p[256];
   };

/* Function prototypes */

long XProtocolSend(struct XPR_IO *xio);

long XProtocolReceive(struct XPR_IO *xio);

long XProtocolCleanup(struct XPR_IO *xio);
struct Vars *setup(struct XPR_IO *io);
UBYTE *find_option(UBYTE *buf, UBYTE option);
void  set_textmode(struct Vars *v);
void  canit(struct Vars *v);
void  zmputs(struct Vars *v, UBYTE *s);
void  xsendline(struct Vars *v, UBYTE c);
void  sendbuf(struct Vars *v);
short readock(struct Vars *v, short tenths);
char  char_avail(struct Vars *v);
void  update_rate(struct Vars *v);
long  bfopen(struct Vars *v, UBYTE *mode);
void  bfclose(struct Vars *v);
void  bfseek(struct Vars *v, long pos);
long  bfread(struct Vars *v, UBYTE *buf, long length);
long  bfwrite(struct Vars *v, UBYTE *buf, long length);
void  ioerr(struct XPR_IO *io, char *msg);
void  upderr(struct Vars *v, char *msg);
void  updmsg(struct Vars *v, char *msg);
#define getfree() (0x7fffffff)
char  exist(struct Vars *v);
#ifdef DEBUGLOG
void  dlog(struct Vars *v, UBYTE *s);
#endif

void  zsbhdr(struct Vars *v, USHORT type);
void  zshhdr(struct Vars *v, USHORT type);
void  zsdata(struct Vars *v, short length, USHORT frameend);
int zrdata(struct Vars *v, UBYTE *buf, short length);
int zrdat32(struct Vars *v, UBYTE *buf, short length);
int zgethdr(struct Vars *v);
int zrbhdr(struct Vars *v);
int zrbhdr32(struct Vars *v);
int zrhhdr(struct Vars *v);
void  zputhex(struct Vars *v, UBYTE c);
void  zsendline(struct Vars *v, UBYTE c);
int zgethex(struct Vars *v);
int zdlread(struct Vars *v);
int noxrd7(struct Vars *v);
void  stohdr(struct Vars *v, long pos);
long  rclhdr(struct Vars *v);

extern ULONG UnixTimeOffset;
ULONG getsystime(struct timeval *tv);

/* End of XprZmodem.h source */
