[comp.os.minix] zmachine part 2/2

leo@marco.UUCP (Matthias Pfaller) (03/13/90)

This is part 2 of zmachine, a interpreter for infocom interactive fiction
games.

	leo@marco.uucp (Matthias Pfaller)


echo x - code.c
sed '/^X/s///' > code.c << '/'
X/*
X*	@(#)code.c	2.24
X*/
X
X#include "zmachine.h"
X
X/*
X* decoding/encoding module
X*/
X
Xchar *codetab = 
X"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ  0123456789.,!?_#'\"/\\-:()\0";
X
Xextern BYTE *short_cuts;
X
X/*
X* decode the string at vaddress a
X*/
X
Xvoid decode(a)
Xstruct address *a;
X{
X    UWORD op;
X    register UWORD d2;
X    register UWORD d4 = 0;
X    register UWORD d5 = 0;
X    register BYTE *p;
X    struct address vaddr;
X    UWORD f76 = 0;
X    BYTE b[3];
X
X    do
X    {
X        op = d2 = fetchw_data(a);
X        for (p = b; p - b < 3; p++)
X        {
X            *p = d2;
X            d2 >>= 5;
X        }
X
X        while (p - b > 0)
X        {
X            d2 = *--p & 0x1f;
X            if (d4 & 0x8000)
X            {
X                waddr_to_vaddr(&vaddr, word_get(&short_cuts[(d2 + f76)*2]));
X		decode(&vaddr);
X                d4 = d5;
X            }
X            else
X            {
X                if (d4 == 3)
X                    d4 = 0x4000 + d2;
X                else if (d4 > 3)
X                {
X                    d4 &= 3;
X                    d4 <<= 5;
X                    d4 |= d2;
X                    output_chr(d4);
X                    d4 = d5;
X                }
X                else
X                {
X                    if (d2 >= 6)
X                    {
X                        if (d4 == 2)
X                        {
X                            if (d2 < 7)
X                                d4++;
X                            else if (d2 == 7)
X                            {
X                                output_chr('\n');
X                                d4 = d5;
X                            }
X                            else
X                            {
X                                output_chr(codetab[d4 * 0x1a + d2 - 6]);
X                                d4 = d5;
X                            }
X                        }
X                        else
X                        {
X                            output_chr(codetab[d4 * 0x1a + d2 - 6]);
X                            d4 = d5;
X                        }
X                    }
X                    else
X                    {
X                        if (d2 == 0)
X                        {
X                            output_chr(' ');
X                            d4 = d5;
X                        }
X                        else
X                        {
X                            if (d2 <= 3)
X                            {
X                                d4 |= ~0x7fff;
X                                f76 = (d2 - 1) << 5;
X                            }
X                            else
X                            {
X                                d2 -= 3;
X                                if (d4 == 0)
X                                    d4 = d2;
X                                else
X                                {
X                                    if (d4 != d2)
X                                        d4 = 0;
X				    d5 = d4;
X                                }
X                            }
X                        }
X                    }
X                }
X            }
X        }
X    }
X    while (!(op & 0x8000));
X}
X
X
X/* return the code group of c */
X
XUWORD code_group(c)
Xregister char c;
X{
X	if (!c)
X		return(3);
X
X	if (c >= 'a' && c <= 'z')
X			return(0);
X
X	if (c >= 'A' && c <= 'Z')
X			return(1);
X
X	return(2);
X}
X
X/*
X* return the index
X* of c in the codetab
X*/
X
XUWORD code_index(c)
Xchar c;
X{
X	register char *p;
X	register UWORD i;
X	char *strchr();
X
X	p = strchr(codetab,c);
X
X	if (p)
X	{
X		for (i = p - codetab + 6; i >= 0x20; i -= 0x1a)
X			;
X		return(i);
X	}
X	else
X		return(0);
X}
X
X
X/*
X* code a word of
X* max 6 chars to dest
X*/
X
Xvoid encode(dst, src)
Xregister UWORD *dst; char *src;
X{
X	register UWORD t, i;
X	register UWORD *tp;
X	UWORD b[12];
X	char c;
X
X	for(tp = b, i = 6; (c = *(src++)) && i; i--)
X	{
X		if (t = code_group(c))
X		{
X			t += 3;
X			*(tp++) = t;
X			if (!--i)
X				break;
X		}
X
X		if (!(t = code_index(c)))
X		{
X			*(tp++) = 6;
X			if (!--i)
X				break;
X			*(tp++) = c >> 5;
X			if (!--i)
X				break;
X
X			t = c & 0x1f;
X		}
X		*(tp++) = t;
X	}
X
X	for (; i; i--)
X		*(tp++) = 5;
X
X	for (tp = b, i = 2; i; i--)
X	{
X		t  = (*tp++ << 10) & (0x1f << 10);
X		t |= (*tp++ <<  5) & (0x1f <<  5);
X		t |= (*tp++)       & (0x1f);
X		*dst++ = t;
X	}
X	dst[-1] |= 0x8000;
X}
/
echo x - config.h
sed '/^X/s///' > config.h << '/'
X/*
X*	@(#)config.h	2.24
X*/
X
X# define I_HIST_LEN	1024	/* len of input history	*/
Xtypedef	char ZWORD[2];		/* zmachine word	*/
Xtypedef unsigned short UWORD;	/* 16 bit unsigned	*/
X#ifndef OSK
Xtypedef short WORD;		/* 16 bit signed	*/
X#endif
Xtypedef unsigned char BYTE;	/* unsigned 8 bit	*/
/
echo x - io.c
sed '/^X/s///' > io.c << '/'
X/*
X*	@(#)io.c	2.24
X*/
X
X# ifdef OSK
X# include <modes.h>
X# endif
X# include "zmachine.h"
X# include "keys.h"
X
Xchar	*iovers = "122400";
Xint	pfile = -1;
XFILE	*fopen();
X
Xchar *print_name = "protocol";
Xint printer_width = 80;
X
X/*****************************************************************************/
X
Xstruct dev *init_dev(out, crlf, l, h, wrap)
Xvoid (*out)(); void (*crlf)(); int l, h, wrap;
X{
X	register struct dev *d;
X
X	if (d = (struct dev *)malloc(sizeof(struct dev) + l))
X	{
X		d->buffer = d->bp = (char *)d + sizeof(struct dev);
X		d->width = l;
X		d->height = h;
X		d->count = 0;
X		d->out_f = out;
X		d->crlf_f = crlf;
X		d->wrap = wrap;
X		return(d);
X	}
X	else
X		no_mem_error();
X}
X
Xvoid putc_dev(c, d)
Xchar c; register struct dev *d;
X{
X	register char *s, *p;
X
X	if (c == '\n' || c == FLUSH)
X	{
X		(*d->out_f)(d->buffer, d->bp);
X		if (c != FLUSH && (d->count != d->width || !d->wrap))
X			(*d->crlf_f)();
X		
X		con_flush();
X
X		d->count = 0;
X		d->bp = d->buffer;
X	}
X	else
X	{
X		if (d->width < d->count+1)
X		{
X			if (c == ' ')
X			{
X				(*d->out_f)(d->buffer, d->bp);
X				if (d->count != d->width || !d->wrap)
X					(*d->crlf_f)();
X				d->count = 0;
X				d->bp = d->buffer;
X				return;
X			}
X			else
X			{
X				for(s = d->bp; --s > d->buffer;)
X					if (*s == ' ')
X						break;
X
X				if (s == d->buffer)
X				{
X					(*d->out_f)(d->buffer, d->bp);
X					d->count = 0;
X					d->bp = d->buffer;
X				}
X				else
X				{
X					(*d->out_f)(d->buffer, s);
X					(*d->crlf_f)();
X					for (d->count = 0, p = d->buffer;
X							 s < d->bp-1;
X								d->count++)
X						*p++ = *++s;
X					d->bp = p;
X				}
X			}
X
X		}
X		*(d->bp++) = c;
X		d->count++;
X	}
X}
X
Xvoid output_chr(c)
Xchar c;
X{
X	extern int use_line, in_status;
X	extern char *line;
X
X	if (c == FLUSH)
X		putc_dev(c, screen);
X	else if (use_line)
X		*line++ = c;
X	else
X	{
X		if (c == 9)
X			c = ' ';
X
X		putc_dev(c, screen);
X
X		if (!in_status && (word_get(main_h->reserved5) & 1))
X			putc_dev(c, printer);
X	}
X}
X
Xvoid output_str(p)
Xregister char *p;
X{
X	while(*p)
X		output_chr(*p++);
X}
X
Xvoid output_status(room, score)
Xchar *room, *score;
X{
X	register char i;
X	register int t;
X	int x,y;
X
X	storeXY(&x, &y);
X	cursorOFF();
X	gotoXY(0,0);
X	reverseON();
X	con_str1(room);
X
X	t = screen->width - strlen(score);
X	for(i = strlen(room); i < t; i++)
X		con_chr(' ');
X
X	con_str1(score);
X	reverseOFF();
X	cursorON();
X	gotoXY(x,y);
X}
X
X/*****************************************************************************/
X
Xvoid more_test()
X{
X	char getc_ne();
X	extern int line_cnt, status_len;
X
X	if ((screen->height - status_len) == ++line_cnt)
X	{
X		status();
X		con_str1("[More]");
X		con_flush();
X		con_getc();
X		con_str1("\r      \r");
X		line_cnt = 2;
X	}
X}
X
Xvoid scr_write(a,b)
Xchar *a, *b;
X{
X	extern int in_status;
X
X	if (!in_status)
X		more_test();
X
X	if (b > a)
X		con_str2(a,b);
X}
X
Xint prot_open()
X{
X	if (pfile == -1)
X	{
X#ifdef OSK
X		if ((pfile = creat(print_name, S_IREAD|S_IWRITE)) < 0)
X#else
X		if ((pfile = creat(print_name, 0666)) < 0)
X#endif
X		{
X			con_crlf();
X			con_str1("Can't open protokoll file");
X			con_crlf();
X			pfile = -2;
X		}
X	}
X	return(pfile >= 0);
X}
X	
Xvoid prot_write(a,b)
Xchar *a, *b;
X{
X		if (prot_open() && (b > a))
X			write(pfile, a, b-a);
X}
X
Xvoid prot_crlf()
X{
X	if (prot_open())
X# if defined(unix) || defined(OSK)
X		write(pfile, "\n", 1);
X# else
X		write(pfile, "\r\n", 2);
X# endif
X}
X
X/*****************************************************************************/
X
Xchar fkeys[10][17];
X
Xint save_keys()
X{
X	extern int save_len;
X	return(write_saveb(save_len + 1, 170, fkeys));
X}
X
Xint restore_keys()
X{
X	extern int save_len;
X	return(read_saveb(save_len + 1, 170, fkeys));
X}
X
Xchar *read_str(p, hist)
Xchar *p; struct hist_buf *hist;
X{
X	extern int line_cnt;
X	register char *q, *src, *dst;
X	char *retype;
X	char *end;
X	register int c;
X	register int i, e;
X	int x, y;
X
X	static char fbuf[18];
X	static char fhmem[36];
X	static struct hist_buf fhist = {36, fhmem, fhmem};
X	static int imode=1;
X	static int init=1;
X	static int fprog = 0;
X
X	if (init)
X	{
X		init = 0;
X		fhmem[0] = fhmem[1] = '\0';
X
X		for(i = F01; i < F10; i++)
X			fkeys[i][0] = '\0';
X	}
X
X	retype = NULL;
X	con_flush();
X
X	(*p)--;			/* we need one char more (for '\0')	*/
X	line_cnt = 1;
X	p[1] = '\0';
X	end = p + p[0] + 1;
X	q = p + 1;
X	while ((c = con_getc()) != RETURN)
X	{
X		switch(c)
X		{
X			case 0x1b:
X				{
X					extern save_gf();
X					save_gf("dump.z");
X				}
X				break;
X
X			case CUP:
X			case CDOWN:
X				if (c == CUP)
X				{
X					if (!retype)
X						retype = hist->undo;
X					else if (*(retype + strlen(retype) + 1))
X						retype += strlen(retype) + 1;
X					else
X						break;
X				}
X				else
X				{
X					if (!retype)
X						retype = hist->undo;
X					else if (retype != hist->hb)
X						for (retype -= 1;
X						  retype != hist->hb &&
X						    retype[-1]; retype--)
X							;
X					else
X						break;
X				}
X
X			case RETYPE:
X				if (!retype)
X					retype = hist->undo;
X
X				/* go to start of input line */
X				e = q - p - 1;
X				cursorOFF();
X				for(i = 0; i < e; i++)
X					cursorLEFT();
X
X				/* delete to end of input line */
X				storeXY(&x, &y);
X				e = strlen(p+1);
X				for (i = 0; i < e; i++)
X					con_chr(' ');
X				gotoXY(x, y);
X
X				/* copy old input line and print it */
X				strncpy(p + 1, retype, *p);
X				*(p + *p + 1) = '\0';
X				con_str1(p + 1);
X				cursorON();
X				q = p + 1 + strlen(p + 1);
X				break;
X
X			case CLEFT:
X				if (q > p + 1)
X				{
X					q--;
X					cursorLEFT();
X				}
X				break;
X
X			case CRIGHT:
X				if (*q != '\0')
X					con_chr(*q++);
X				break;
X
X			case START:
X				e = q - p - 1;
X				cursorOFF();
X				for(i = 0; i < e; i++)
X					cursorLEFT();
X				cursorON();
X				q = p + 1;
X				break;
X
X			case END:
X				cursorOFF();
X				con_str1(q);
X				cursorON();
X				q += strlen(q);
X				break;
X
X			case BACKDEL:
X				if (q > p + 1)
X				{
X					cursorLEFT();
X					storeXY(&x, &y);
X					strcpy(q-1, q);
X					q--;
X					cursorOFF();
X					con_str1(q);
X					con_chr(' ');
X					gotoXY(x, y);
X					cursorON();
X				}
X				break;
X
X			case FORWDEL:
X				if (*q != '\0')
X				{
X					storeXY(&x, &y);
X					strcpy(q, q + 1);
X					cursorOFF();
X					con_str1(q);
X					con_chr(' ');
X					gotoXY(x, y);
X					cursorON();
X				}
X				break;
X
X			case KILL:
X				if (*q != '\0')
X				{
X					storeXY(&x, &y);
X					cursorOFF();
X					e = strlen(q);
X					for (i = 0; i < e; i++)
X						con_chr(' ');
X					*q = '\0';
X					gotoXY(x, y);
X					cursorON();
X				}
X				break;
X
X			case INSERT:
X				imode = !imode;
X				break;
X
X			case FPROG:
X				if(!fprog)
X				{
X					fprog = 1;
X					cursorOFF();
X					storeXY(&x, &y);
X					gotoXY(0, 0);
X					reverseON();
X					for (i = 0; i < screen->width; i++)
X						con_chr(' ');
X					gotoXY(0, 0);
X					con_str1("Press function key: ");
X					cursorON();
X					con_flush();
X					do
X						c = con_getc();
X					while(c < FSTART);
X					cursorOFF();
X					con_str1("\r                    \r");
X					con_str1("Enter text: ");
X					fbuf[0] = 17;
X					cursorON();
X					con_flush();
X					read_str(fbuf, &fhist);
X					cursorOFF();
X					status();
X					gotoXY(x, y);
X					cursorON();
X					strcpy(fkeys[c - FSTART], fbuf + 1);
X					fprog = 0;
X				}
X				break;
X
X			default:
X				if (strlen(p + 1) < p[0] || (*q && !imode))
X				{
X					if (c >= ' ' && c < 0x80)
X					{
X						if (imode)
X						{
X							for (src = q + strlen(q),
X								dst = q + strlen(q) + 1;
X								src >= q;
X								*dst-- = *src--)
X								;
X							*q = c;
X							cursorOFF();
X							con_str1(q++);
X							e = strlen(q);
X							for(i = 0; i < e; i++)
X								cursorLEFT();
X							cursorON();
X						}
X						else
X						{
X							if (!*q)
X								*(q+1) = '\0';
X							*q++ = c;
X							con_chr(c);
X						}
X					}
X					else if (c >= FSTART)
X					{
X						if (!*q)
X						{
X							strncpy(q, fkeys[c - FSTART], end - q);
X							cursorOFF();
X							con_str1(q);
X							cursorON();
X							q += strlen(q);
X						}
X						else if (imode)
X						{
X							if (end - q - strlen(q) < strlen(fkeys[c - FSTART]))
X								dst = end + 1;
X							else
X								dst = q + strlen(fkeys[c - FSTART]) + strlen(q) + 1;
X
X							cursorOFF();
X							for (src = q + strlen(q) + 1; src >= q; *dst-- = *src--)
X								;
X
X							for(src = fkeys[c - FSTART]; q <= dst;)
X								con_chr(*q++ = *src++);
X
X							con_str1(q);
X							e = strlen(q);
X							for(i = 0; i < e; i++)
X								cursorLEFT();
X							cursorON();
X						}
X						else
X						{
X							if(strlen(q) < strlen(fkeys[c - FSTART]))
X							{
X								strncpy(q, fkeys[c - FSTART], end - q);
X								dst = q + strlen(fkeys[c - FSTART]);
X								dst = (dst < end)?dst:end;
X							}
X							else
X							{
X								for(src = fkeys[c - FSTART], dst = q; *src && dst < end; *dst++ = *src++)
X									;
X							}
X							cursorOFF();
X							con_str2(q, dst);
X							cursorON();
X							q = dst;
X						}
X					}
X				}	
X		}
X		con_flush();
X	}
X
X	(*p)++;		/* restore original maxlen	*/
X
X	if (!retype)
X		retype = hist->undo;
X
X	if (strcmp(retype, p + 1) && strlen(p + 1))
X	{
X		for (src = hist->hb + hist->len - strlen(p + 1) - 2,
X		  dst = hist->hb + hist->len - 1;
X		    src >= hist->hb; *dst-- = *src--)
X			;
X
X		strcpy(hist->hb, p + 1);
X
X		hist->hb[hist->len - 2] = hist->hb[hist->len - 1] = '\0';
X		hist->undo = hist->hb;
X	}
X	else
X		hist->undo = retype;
X
X	cursorOFF();
X	con_str1(q);
X	cursorON();
X	putc_dev('\n', screen);
X	con_flush();
X	return(p + strlen(p + 1) + 1);
X}
/
echo x - zbios.c
sed '/^X/s///' > zbios.c << '/'
X/*
X*	@(#)zbios.c	2.24
X*	Basic input/output System for ZMACHINE
X*	all machine dependent functions are collected
X*	in this file.
X*/
X
X#include	<fcntl.h>
X#include	<ctype.h>
X#ifdef	OSK
X#include	<modes.h>
X#endif
X#include	"zmachine.h"
X#include	"keys.h"
X
X#ifdef GEMDOS
Xchar	*sysname = "Atari ST";
X
X#include <sys\osbind.h>
X#endif
X
X#if defined(unix) || defined(OSK)
X#ifdef unix
Xchar	*sysname = "u**x";
X
X#include <sgtty.h>
X#include <signal.h>
X#include <sys/types.h>
X
Xstruct sgttyb otermio,ntermio;
X#endif
X#ifdef OSK
Xchar	*sysname = "OS9/68000";
X
X#include <sgstat.h>
X#define	fputc(a,b)	putc(a,b)
X#define gtty(FD,ADR)     getstat(0,FD,ADR)
X#define stty(FD,ADR)     setstat(0,FD,ADR)
X#define CHRAW(X)    chraw( & X)
Xstruct sgbuf nstate, ostate;
X
X#define PC PC_
Xint ospeed = 0;
X
Xchraw(x)
Xstruct sgbuf *x;
X{
X	x->sg_case = 0;
X	x->sg_backsp = 0;
X	x->sg_echo = 0;
X	x->sg_alf = 0;
X	x->sg_pause = 0;
X	x->sg_bspch = 0x80;
X	x->sg_dlnch = 0x80;
X	x->sg_eorch = 0x80;
X	x->sg_eofch = 0x80;
X	x->sg_rlnch = 0x80;
X 	x->sg_dulnch = 0x80;
X	x->sg_psch = 0x80;
X	x->sg_kbich = 0x80;
X	x->sg_kbach = 0x80;
X	x->sg_bsech = 0x80;
X	x->sg_bellch = 0x80;
X	x->sg_tabcr = 0x80;
X	x->sg_xon = 0x11;
X	x->sg_xoff = 0x13;
X}
X#endif
X
Xchar tcapbuf[1024];
Xchar *CM = NULL, *CL = NULL, *BC = NULL, *UP = NULL, *DL = NULL, *TI = NULL, *TE = NULL, *SE = NULL, *SO = NULL, PC = '\0', *VS = NULL, *VE = NULL;
Xchar *KS = NULL, *KE = NULL;
X
Xstruct fkencode
X	{
X		struct fkencode *nextchar;    /* next char in string */
X		struct fkencode *nextstring;  /* next string         */
X		int fkc;		      /* current char
X					         > 0x100 = return    */
X	} *fkroot = NULL;
X
Xstruct
X	{
X		char *name;
X		int code;
X	} keylist[] = {
X		{ "kl", CLEFT },
X		{ "kr", CRIGHT },
X		{ "ku", CUP },
X		{ "kd", CDOWN },
X		{ "kb", BACKDEL },
X
X		{ "k0", FSTART + F01 },
X		{ "k1", FSTART + F02 },
X		{ "k2", FSTART + F03 },
X		{ "k3", FSTART + F04 },
X		{ "k4", FSTART + F05 },
X		{ "k5", FSTART + F06 },
X		{ "k6", FSTART + F07 },
X		{ "k7", FSTART + F08 },
X		{ "k8", FSTART + F09 },
X		{ "k9", FSTART + F10 },
X		{ NULL, 0 }
X	};
X
Xstruct fkencode *insertc(fk, c)
Xstruct fkencode *fk; int c;
X{
X	if (!fk)
X	{
X		if (!(fk = (struct fkencode *)malloc(sizeof(struct fkencode))))
X			no_mem_error();
X		fk->nextchar = fk->nextstring = NULL;
X		fk->fkc = c;
X		return(fk);
X	}
X	else
X	{
X		if (fk->fkc == c)
X			return(fk);
X		else
X		{
X			if (!fk->nextstring)
X			{
X				fk->nextstring = insertc(NULL, c);
X				fk = fk->nextstring;
X			}
X			else
X				fk = insertc(fk->nextstring, c);
X
X			return(fk);
X		}
X	}
X}
X
Xstruct fkencode *insertkey(fk, s, c)
Xstruct fkencode *fk; char *s; int c; 
X{
X	struct fkencode *root;
X
X	if (fk)
X	{
X		root = fk;
X		fk = insertc(fk, *s++);
X	}
X	else
X		root = fk = insertc(NULL, *s++);
X
X	while(*s)
X	{
X		if (fk->nextchar)
X			fk = insertc(fk->nextchar, *s++);
X		else
X		{
X			fk->nextchar = insertc(NULL, *s++);
X			fk = fk->nextchar;
X		}
X	}
X
X	fk->nextchar = insertc(NULL, c);
X	return(root);
X}
X
X#endif
X
Xint	story	= -1;
Xint	save	= -1;
X
Xstruct	{
X		int x, y, lline, lchar;
X	} con;
X
Xstruct dev *screen;
X
Xvoid	icon_str();
Xvoid	icon_chr();
X/*
X*	long random()	-	return a random number (range 0 - min 0x7fff)
X*/
X
Xlong zrandom()
X{
X#ifdef GEMDOS
X	return(Random());
X#endif
X#if defined(unix) || defined(OSK)
X	extern void srand();
X	extern long rand();
X	extern long time();
X
X	static int init = 1;
X
X	if (init)
X	{
X		init = 0;
X		srand((int)time(NULL));
X	}
X
X	return(rand());
X#endif
X}
X
X/*
X*	con_flush()	-	flush the console output buffer
X*/
X
Xvoid con_flush()
X{
X#if defined(unix) || defined(OSK)
X	fflush(stdout);
X#endif
X}
X
X/*
X*	con_chr(c)	-	output the single character c to
X*	char c;			the console-device
X*/
X
Xvoid con_chr(c)
Xchar c;
X{
X	int x,y;
X	if (c == '\r')
X	{
X		gotoXY(0, con.y);
X		return;
X	}
X	else if (con.x++ == con.lchar)
X	{
X		storeXY(&x, &y);
X		con_crlf();
X		if (y == con.lline)
X			y--;
X		gotoXY(x, y);
X#ifdef GEMDOS
X		Bconout(2,c);
X#else
X		putchar(c);
X#endif
X		gotoXY(0,y+1);
X	}
X	else
X#ifdef GEMDOS
X		Bconout(2,c);
X#else
X		putchar(c);
X#endif
X
X}
X
X/*
X*	con_str1(p)		-	output a '\0' terminated string to
X*	char *p;			the console-device
X*/
X
Xvoid con_str1(p)
Xregister char *p;
X{	while(*p)
X		con_chr(*p++);
X}
X
X/*
X*	con_str2(p,q)		-	output the string p with the
X*	char *p, *q;			endaddress q to the console-device
X*
X*/
X
Xvoid con_str2(p,q)
Xregister char *p,*q;
X{
X	while(p < q)
X		con_chr(*p++);
X}
X
X/*
X*	con_crlf()		-	scroll all lines but first
X*					status_len lines (if possible).
X*					goto first column of next line.
X*/
X
Xvoid con_crlf()
X{
X	extern int status_len;
X#if defined(unix) || defined(OSK)
X	int x,y;
X#endif
X
X	if (con.y == con.lline)
X	{
X#ifdef GEMDOS
X		icon_str("\033j\033f\033Y");
X		icon_chr(' ' + status_len);
X		icon_str(" \033M\033k\r\033e");
X#endif
X#if defined(unix) || defined(OSK)
X		storeXY(&x,&y);
X		cursorOFF();
X		if (DL)
X		{
X			gotoXY(0,status_len);
X			putpad(DL);
X		}
X		else
X		{
X			gotoXY(0, con.lline);
X#ifdef OSK
X			icon_str("\012");
X#else
X			icon_str("\n");
X#endif
X		}
X		x = 0;
X		gotoXY(x,y);
X		cursorON();
X#endif
X	}
X	else
X	{
X#ifdef OSK
X		icon_str("\015\012");
X#else
X		icon_str("\r\n");
X#endif
X		con.y++;
X	}
X	con.x = 0;
X}
X
X/*
X*	reverseON()		-	turn reversemode on
X*	reverseOFF()		-	turn reversemode off
X*/
X
Xvoid reverseON()
X{
X#ifdef GEMDOS
X	icon_str("\033p");
X#endif
X#if defined(unix) || defined(OSK)
X	if (SO)  
X		putpad(SO);
X#endif
X}
X
Xvoid reverseOFF()
X{
X#ifdef GEMDOS
X	icon_str("\033q");
X#endif
X#if defined(unix) || defined(OSK)
X	if (SE)
X		putpad(SE);
X#endif
X}
X
X/*
X*	cursorON()		-	turn cursor on
X*	cursorOFF()		-	turn cursor off
X*/
X
Xvoid cursorON()
X{
X#ifdef GEMDOS
X	icon_str("\033e");
X#endif
X}
X
Xvoid cursorOFF()
X{
X#ifdef GEMDOS
X	icon_str("\033f");
X#endif
X}
X
X/*
X*	cursorLEFT()		-	move cursor left (with wrap)
X*/
X
XcursorLEFT()
X{
X	if (con.x)
X	{
X#ifdef GEMDOS
X		icon_chr(8);
X#endif
X#if defined(unix) || defined(OSK)
X		icon_str(BC);
X#endif
X		con.x--;
X	}
X	else
X		gotoXY(con.lchar, con.y - 1);
X}
X
X/*
X*	gotoXY(x,y)		-	goto screen position x,y
X*	int x,y;
X*/
X
Xvoid gotoXY(x,y)
Xint x,y;
X{
X#ifdef GEMDOS
X	icon_str("\033Y");
X	icon_chr(' ' + y);
X	icon_chr(' ' + x);
X#endif
X#if defined(unix) || defined(OSK)
X	extern char *tgoto();
X	putpad(tgoto(CM, x, y));
X#endif
X	con.x = x;
X	con.y = y;
X}
X
X/*
X*	storeXY(x,y)		-	store current cursor position to
X*	int *x, *y;			x and y
X*/
X
Xvoid storeXY(x,y)
Xint *x, *y;
X{
X	*x = con.x;
X	*y = con.y;
X}
X
X/*
X*	int con_getc()	-		get a character from the console
X*					handle special chars.
X*/
X
X#ifdef GEMDOS
Xint con_getc()
X{
X	long c;
X	static int s = 16;
X	c = Bconin(2);
X	switch((int)(c >> s))		/* compiler error */
X	{
X		case 0x004b:
X			return(CLEFT);
X
X		case 0x004d:
X			return(CRIGHT);
X
X		case 0x0050:
X			return(CDOWN);
X
X		case 0x0048:
X			return(CUP);
X
X		case 0x0061:
X			return(RETYPE);
X
X		case 0x0052:
X			return(INSERT);
X
X		case 0x0073:
X			return(START);
X
X		case 0x0074:
X			return(END);
X
X		default:
X			if ((c >> s) > 0x003a && (c >> s) < 0x0045)
X				return(FSTART + (c >> s) - 0x003b);
X
X			switch((int)(c&0xff))
X			{
X				case 0x01:
X					return(START);
X
X				case 0x05:
X					return(END);
X
X				case 0x19:
X					return(RETYPE);
X
X				case 0x0b:
X					return(KILL);
X
X				case 0x08:
X					return(BACKDEL);
X
X				case 0x7f:
X					return(FORWDEL);
X
X				case 0x04:
X					return(FORWDEL);
X
X				case 0x02:
X					return(CLEFT);
X
X				case 0x06:
X					return(CRIGHT);
X
X				case 0x0e:
X					return(CDOWN);
X
X				case 0x10:
X					return(CUP);
X
X				case 0x09:
X					return(FPROG);
X
X				case 0x0d:
X					return(RETURN);
X
X				default:
X					return(c&0xff);
X			}
X	}
X}
X#else
Xint con_getc()
X{
X	char c;
X	register struct fkencode *fk;
XRETRY:
X	read(0, &c, 1);
X	c &= 0x7f;
X	for (fk = fkroot; fk;)
X	{
X		if (fk && c == fk->fkc)
X		{
X			fk = fk->nextchar;
X			if (fk && fk->fkc > 0x100)
X				return(fk->fkc);
X			else
X			{
X				read(0, &c, 1);
X				c &= 0x7f;
X			}
X		}
X		else
X			fk = fk->nextstring;
X	}
X
X	switch((int)(c&0xff))
X	{
X		case 0x18:
X			read(0, &c, 1);
X			c &= 0x0f;
X			if (c > 9)
X				goto RETRY;
X			return(c + FSTART);
X
X		case 0x01:
X			return(START);
X
X		case 0x05:
X			return(END);
X
X		case 0x19:
X			return(RETYPE);
X
X		case 0x0b:
X			return(KILL);
X
X		case 0x7f:
X			return(BACKDEL);
X
X		case 0x08:
X			return(FORWDEL);
X
X		case 0x04:
X			return(FORWDEL);
X
X		case 0x02:
X			return(CLEFT);
X
X		case 0x06:
X			return(CRIGHT);
X
X		case 0x0e:
X			return(CDOWN);
X
X		case 0x10:
X			return(CUP);
X
X		case 0x09:
X			return(FPROG);
X
X		case '\n':
X#ifndef OSK
X		case 0x0d:
X#endif
X			return(RETURN);
X
X		default:
X			return(c&0xff);
X	}
X}
X#endif
X
X/*
X*	init_con()		-	initialize console
X*					- clear screen
X*					- goto last line on screen
X*/
X
Xvoid init_con()
X{
X	int len;
X	int lines;
X	static int init=1;
X#if defined(unix) || defined(OSK)
X	char *getenv(), *tgetstr();
X	char *p, *t, *tv_stype;
X	int i;
X	void clean_up();
X	char tcbuf[1024];
X#endif
X
X#ifdef GEMDOS
X	if (Getrez())
X		len = 80;
X	else
X		len = 40;
X	lines = 25;
X#endif
X
X#if defined(unix) || defined(OSK)
X	if (init)
X	{
X#ifdef unix
X		ioctl(0, TIOCGETP, &otermio);
X		ntermio = otermio;
X		ntermio.sg_flags |= RAW;
X		ntermio.sg_flags &= ~(ECHO|CRMOD);
X		ioctl(0, TIOCSETP, &ntermio);
X#endif
X#ifdef OSK
X		gtty(0, &ostate);
X		gtty(0, &nstate);
X		CHRAW(nstate);
X		stty(0, &nstate);
X#endif
X		if ((tv_stype = getenv("TERM")) == NULL)
X			fatal("Environment variable TERM not defined", NULL);
X
X		if (tgetent(tcbuf, tv_stype) != 1)
X			fatal("Unknown terminal type", tv_stype);
X
X		if ((lines = tgetnum("li")) == -1)
X			fatal("Termcap entry incomplete (lines)", tv_stype);
X
X		if ((len = tgetnum("co")) == -1)
X			fatal("Termcap entry inclomplete (columns)", tv_stype);
X
X		p = tcapbuf;
X		t = tgetstr("pc", &p);
X		if (t)
X			PC = *t;
X
X		CM = tgetstr("cm", &p); /* cursor movement	*/
X
X		CL = tgetstr("cl", &p); /* clear screen 	*/
X
X		UP = tgetstr("up", &p); /* cursor up		*/
X
X		SE = tgetstr("se", &p); /* exit reverse mode	*/
X
X		SO = tgetstr("so", &p); /* enter reverse mode	*/
X
X		BC = tgetstr("bc", &p); /* back space char	*/
X		if (!BC)
X			BC = "\010";
X
X		DL = tgetstr("dl", &p); /* delete line		*/
X
X		TI = tgetstr("ti", &p); /* terminal init	*/
X
X		TE = tgetstr("te", &p); /* terminal reset	*/
X
X		VS = tgetstr("vs", &p); /* enter visual mode	*/
X
X		VE = tgetstr("ve", &p); /* exit visual mode	*/
X
X		KS = tgetstr("ks", &p); /* enter visual mode	*/
X
X		KE = tgetstr("ke", &p); /* enter visual mode	*/
X
X		if (!CM || !CL || !UP)
X			fatal("Termcap entry inclomplete", tv_stype);
X
X		for (i = 0; keylist[i].name; i++)
X			if ( t = tgetstr(keylist[i].name, &p))
X				fkroot = insertkey(fkroot, t, keylist[i].code);
X
X	}
X#endif
X	if (init)
X	{
X		con.lline = lines - 1;
X		con.lchar = len - 1;
X	}
X#ifdef GEMDOS
X	icon_str("\033E\033w");		/* cursor on, wrap off */
X#endif
X#if defined(unix) || defined(OSK)
X	if (init)
X	{
X		if (TI)
X			icon_str(TI);
X
X		if (VS)
X			icon_str(VS);
X
X		if (KS)
X			icon_str(KS);
X	}
X	icon_str(CL);
X#endif
X	gotoXY(0, con.lline);
X	cursorON();
X	if (init)
X		screen = init_dev(scr_write, con_crlf, len, lines, 1);
X
X	screen->bp = screen->buffer;
X	screen->count = 0;
X	init = 0;
X}
X
X/*
X*	open_story		-	open the storyfile specified by the
X*					global variable story_name
X*/
X
Xint open_story()
X{
X	return((story = open(story_name, O_RDONLY)) < 0);
X}
X
X/*
X*	close_story		-	close the story file
X*/
X
Xint close_story()
X{
X	int st;
X	st = close(story);
X	story = -1;
X	return(st);
X}
X
X/*
X*	read_story(p, n, bp)	-	read n pages (512 byte) from page no. p
X*	unsigned p, n; char *bp;	to the address bp
X*/
X
Xvoid read_story(p, n, bp)
Xunsigned p, n; BYTE *bp;
X{
X	if (read_pages(story, p, n, bp))
X		fatal("story file read error", story_name);
X}
X
Xvoid read_header(p)
Xstruct header *p;
X{
X	if (read(story, p, sizeof(struct header)) != sizeof(struct header))
X		fatal("can't read story header", story_name);
X}
X
X/*
X*	open_save_w(name)	-	open the save file name for writing
X*	char *name;
X*/
X
Xint open_save_w(name)
Xchar *name;
X{
X#ifdef OSK
X	return((save = creat(name, S_IREAD|S_IWRITE)) < 0);
X#else
X	return((save = creat(name, 0666)) < 0);
X#endif
X}
X
X/*
X*	open_save_r(name)	-	open the save file name for reading
X*	char *name;
X*/
X
Xint open_save_r(name)
Xchar *name;
X{
X	return((save = open(name, O_RDONLY)) < 0);
X}
X
X/*
X*	close_save()		-	close the save file
X*/
X		
Xint close_save()
X{
X	int st;
X	st = close(save);
X	save = -1;
X#ifdef OSK
X	return(0);
X#else
X	return(st);
X#endif
X}
X
X/*
X*	read_save(p, n, bp)	-	read n pages (512 byte) from page no. p
X*	unsigned p, n; char *bp;	to the address bp
X*/
X
Xint read_save(p, n, bp)
Xunsigned p, n; BYTE *bp;
X{
X	return(read_pages(save, p, n, bp));
X}
X
X/*
X*	write_save(p, n, bp)	-	write n pages (512 byte) to page no. p
X*	unsigned p, n; char *bp;	from the address bp
X*/
X
Xint write_save(p, n, bp)
Xunsigned p, n; BYTE *bp;
X{
X	return(write_pages(save, p, n, bp));
X}
X
X/*
X*	write_saveb(p, n, bp)	-	write n bytes to page no. p from the
X*	unsigned p, n; BYTE *bp;	address bp
X*/
X
Xint write_saveb(p, n, bp)
Xunsigned p, n; BYTE *bp;
X{
X	long lseek(), lwrite();
X	if (lseek(save, (long)p * 0x200L, 0) != (long)p * 0x200L)
X		return(1);
X
X	return(lwrite(save, bp, (long)n) != (long)n);
X}
X
X/*
X*	read_saveb(p, n, bp)	-	read n bytes from page no. p to the
X*	unsigned p, n; BYTE *bp;	address bp
X*/
X
Xint read_saveb(p, n, bp)
Xunsigned p, n; BYTE *bp;
X{
X	long lseek(), lread();
X	if (lseek(save, (long)p * 0x200L, 0) != (long)p * 0x200L)
X		return(1);
X
X	return(lread(save, bp, (long)n) < 0L);
X}
X
X/*
X*	char *read_rname()	-	ask user for restore file
X*/
X
Xchar *read_rname()
X{
X	static char name[129];
X	static struct hist_buf nam_hist = {256, NULL};
X
X	if (!nam_hist.hb)
X	{
X		if (!(nam_hist.undo = nam_hist.hb = malloc(nam_hist.len)))
X			no_mem_error();
X		else
X			nam_hist.hb[0] = nam_hist.hb[1] = '\0';
X	}
X
X	name[0] = 128;
X
X	con_str1("Default name is: ");
X	con_str1(nam_hist.undo);
X	con_crlf();
X	con_str1("Enter file name: ");
X	read_str(name, &nam_hist);
X
X	return(*nam_hist.undo?nam_hist.undo:NULL);
X}
X
X/*
X*	char *read_sname()	-	ask user for save file
X*/
X
Xchar *read_sname()
X{
X	char *name;
X	char c;
X	if (name = read_rname())
X	{
X		if (!access(name,0))
X		{
X			con_str1("You are about to write over an existing file. Proceed? (Y/N) ");
X			con_flush();
X			while ((c = toupper(con_getc())) != 'Y' && c != 'N')
X				;
X			con_chr(c);
X			con_crlf();
X			if (c == 'N')
X				return(NULL);
X		}
X		return(name);
X	}
X	else
X		return(NULL);
X}
X
X/*****************************************************************************/
X/*				utility functions			     */
X
X#ifdef GEMDOS
Xlong lread(fd, bp, n)
Xint fd; BYTE *bp; long n;
X{
X	return(Fread(fd, n, bp));
X}
X
Xlong lwrite(fd, bp, n)
Xint fd; BYTE *bp; long n;
X{
X	return(Fwrite(fd, n, bp));
X}
X#endif
X
Xint write_pages(fd, p, n, bp)
Xint fd; unsigned p, n; BYTE *bp;
X{
X	long lseek();
X	if (lseek(fd, (long)p * 0x200L, 0) != (long)p * 0x200L)
X		return(1);
X
X	return(lwrite(fd, bp, 0x200L * (long)n) != (0x200L * (long)n));
X}
X
Xint read_pages(fd, p, n, bp)
Xint fd; unsigned p, n; BYTE *bp;
X{
X	if (lseek(fd, (long)p * 0x200L, 0) != (long)p * 0x200L)
X		return(1);
X
X	return(lread(fd, bp, 0x200L * (long)n) < 0L);
X}
X
Xvoid icon_str(p)
Xregister char *p;
X{
X	while(*p)
X#ifdef GEMDOS
X		Bconout(2,*p++);
X#else
X		putchar(*p++);
X#endif
X}
X
Xvoid icon_chr(c)
Xchar c;
X{
X#ifdef GEMDOS
X	Bconout(2,c);
X#else
X	putchar(c);
X#endif
X}
X
Xvoid fatal(s1, s2)
Xchar *s1, *s2;
X{
X	write(2,"ERROR",5);
X	if (s2) {
X		write(2," [",2);
X		write(2,s2,strlen(s2));
X		write(2,"]",1);
X	}
X	write(2,": ",2);
X	write(2,s1,strlen(s1));
X# ifdef GEMDOS
X	write(2,"\n\r",2);
X# else
X	write(2,"\n",1);
X# endif
X	clean_up();
X	exit(userexit(1));
X}
X
Xvoid clean_up()
X{
X	if (story >= 0)
X		close_save();
X
X	if (save >= 0)
X		close_story();
X
X	if (pfile >= 0)
X		close(pfile);
X
X#if defined(unix) || defined(OSK)
X	if (TE)
X		icon_str(TE);
X	if (VE)
X		icon_str(VE);
X
X	if (KE)
X		icon_str(KE);
X
X#ifdef unix
X	if (ntermio.sg_flags & RAW)
X		ioctl(0, TIOCSETP, &otermio);
X#endif
X#ifdef OSK
X	if (nstate.sg_tabcr == (char)(0x80))
X		stty(0, &ostate);
X#endif
X	icon_chr('\n');
X
X#endif
X}
X
Xint userexit(s)
Xint s;
X{
X	char *getenv();
X
X#ifdef GEMDOS
X	if (!getenv("ARGV"))
X	{
X		write(2, "\n\rStrike any key to exit ", 24);
X		con_getc();
X	}
X#endif
X	return(s);
X}
X
X#if defined(unix) || defined(OSK)
Xputpad(s)
Xchar *s;
X{
X	tputs(s, 1, icon_chr);
X}
X
X#if !defined(CADMUS) && !defined(minix)
Xchar *lmalloc(n)
Xlong n;
X{
X	return(malloc(n));
X}
X#endif
X
X#if !defined(minix)
Xlong lread(a,b,c)
Xint a; char *b; int c;
X{
X	return (read(a,b,c));
X}
X
Xlong lwrite(a,b,c)
Xint a; char *b; int c;
X{
X	return(write(a,b,c));
X}
X#else
Xlong lread(fd, bp, cnt)
Xint fd; char *bp; long cnt;
X{
X	register int n, b;
X	register long bcnt;
X	bcnt = cnt;
X	while(bcnt)
X	{
X		n = read(fd, bp, (int)(b = bcnt>31744?31744:bcnt));
X		if (n < 0)
X			return(n);
X		if (n < b)
X			return(bcnt - n);
X		bcnt -= n;
X		bp += n;
X	}
X	return(cnt);
X}
X
Xlong lwrite(fd, bp, cnt)
Xint fd; char *bp; long cnt;
X{
X	register int n, b;
X	register long bcnt;
X	bcnt = cnt;
X	while(bcnt)
X	{
X		n = write(fd, bp, (int)(b = bcnt>31744?31744:bcnt));
X		if (n < 0)
X			return(n);
X		if (n < b)
X			return(bcnt - n);
X		bcnt -= n;
X		bp += n;
X	}
X	return(cnt);
X}
X
X#endif
/
echo x - keys.h
sed '/^X/s///' > keys.h << '/'
X/*
X*	@(#)keys.h	2.24
X*/
X
X#define	CLEFT	0x180
X#define	CRIGHT	0x181
X#define	START	0x182
X#define	END	0x183
X#define	BACKDEL	0x184
X#define	FORWDEL	0x185
X#define	KILL	0x186
X#define	INSERT	0x187
X#define	RETURN	0x188
X#define	RETYPE	0x189
X#define	CDOWN	0x18a
X#define	CUP	0x18b
X#define FPROG	0x18c
X#define	FSTART	0x200
X#define	F01	0x01
X#define	F02	0x02
X#define	F03	0x03
X#define	F04	0x04
X#define	F05	0x05
X#define	F06	0x06
X#define	F07	0x07
X#define	F08	0x08
X#define	F09	0x09
X#define	F10	0x0a
/

leo@marco.UUCP (Matthias Pfaller) (03/14/90)

Sorry, but I have forgotten the makefiles;
I received the pcminix-makefile from Robert R. Hall (hall@nosc.mil). I
hope it will work. In the file zbios.c the last line got somehow lost.
Please insert a '#endif' as the last line.

	leo@marco.UUCP (Matthias Pfaller)

# -------------------- cut ---------------------
echo x - stminix.mk
sed '/^X/s///' > stminix.mk << '/'
XOBJS	=	zmachine.o \
X		io.o \
X		mem.o \
X		code.o \
X		zbios.o
X
XBIN	=	$(HOME)/bin
X
XCFLAGS	=	-O -Dunix -Dminix
X
Xall:	zmachine
X
Xzmachine:	$(OBJS)
X	$(CC) -o zmachine $(OBJS)
X
X$(OBJS):	zmachine.h config.h
X
Xio.o bios.o:	keys.h
X
Xinstall:	all
X	cp zmachine $(BIN)/zmachine
X	strip $(BIN)/zmachine
/
echo x - pcminix.mk
sed '/^X/s///' > pcminix.mk << '/'
XCFLAGS=  -F -D_MINIX -D_POSIX_SOURCE -Dminix -Dunix
XLDFLAGS        =-i
X
XOBJS   =code.s io.s mem.s zbios.s zmachine.s
X
Xzmachine: $(OBJS)
X	asld $(LDFLAGS) -o zmachine $(OBJS)
X
Xclean:
X	@rm $(OBJS)
X
/

leo@marco.UUCP (Matthias Pfaller) (03/16/90)

Sorry again,
I have forgotten, that I have changed my stdio.h and my fcntl.h.
You have to include sys/types.h in zbios.c before including fcntl.h.
You have to insert a
---
#undef NULL
#define NULL ((char *)0)
---
after including stdio.h in zmachine.h.
      leo@marco.UUCP (Matthias Pfaller)