/*
 * Global procedures and variables
 *
 * Copywrite 1993, Hamish Coleman
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <termio.h>
#include <termcap.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/times.h>
#include <sys/time.h>
#include <limits.h>
#include <linux/fd.h>
#include "global.h"
#include "termio.h"
#include "bios.h"

struct vm86_struct vm86s;
struct timeval scr_tv;
unsigned char outbuf[OUTBUFSIZE], *outp = outbuf;
int hdiskboot =1;
long start_time;
int screen_bitfield;
int screen, xpos[8], ypos[8];

int outcbuf(int c)
{
  CHOUT(c);
  return 1;
}

void clear_screen(int s, int att)
{
	us *sadr, *p, blank = ' ' | (att << 8);

	if (s > 7) return;
	if (s == screen) tputs(cl, 1, outc);
	xpos[s] = ypos[s] = 0;
	sadr = SCREEN_ADR(s);
	for (p = sadr; p < sadr+2000; *p++ = blank);
	screen_bitfield = 0;
}

void restore_screen(int bitmap)
{
	us *sadr, *p; 
	unsigned char c, a;
	int x, y, oa;

	if ((bitmap & (1 << (24 + screen))) == 0) return;
	/* debmsg("RESTORE SCREEN 0x%x\n", screen_bitfield); */
	sadr = SCREEN_ADR(screen);
	oa = 7;
	p = sadr;
	for (y=0; y<LI; y++) {
		tputs(tgoto(cm, 0, y), 1, outcbuf);
		for (x=0; x<CO; x++) {
			c = *(unsigned char *)p;
			if ((a = ((unsigned char *)p)[1]) != oa) {
				if ((a & 7) == 0) tputs(mr, 1, outcbuf);
				else tputs(me, 1, outcbuf);
				if ((a & 0x88)) tputs(md, 1, outcbuf);
				oa = a;
			}
			CHOUT(trans[c] ? trans[c] : '_');
			p++;
		}
	}
	tputs(me, 1, outcbuf);
	CHFLUSH;
	poscur(xpos[screen],ypos[screen]);
	screen_bitfield = 0;
}

void show_regs(void)
{
	int i;
	char s[100];
	char *diss = s;
	int ilen;

	unsigned char *cp = (unsigned char *)0 + (_regs.cs<<4) + _regs.eip;

	debmsg("bp=%08x  sp=%04x:%04x  flags=%08x  ds=%04x  es=%04x  fs=%04x  gs=%04x\n", _regs.ebp, 
		_regs.ss, _regs.esp, _regs.eflags, _regs.ds & 0xffff, _regs.es & 0xffff, _regs.fs & 0xffff, _regs.gs & 0xffff);
	debmsg("ax=%08x  bx=%08x  cx=%08x  dx=%08x  di=%08x  si=%08x\n", _regs.eax, _regs.ebx, 
		_regs.ecx, _regs.edx, _regs.edi, _regs.esi);
	debmsg("%04x:%04x ",_regs.cs,_regs.eip);

	ilen = i386dis(2,_regs.cs,_regs.eip,cp,diss);
	for (i=0; i<ilen; i++)
		debmsg("%02x", *cp++);
	debmsg("\r\t\t\t%s\n\n",diss);
}

void dump_hex(u_char * buf, long len)
{
	int i;
	int j;
	char prt[17];
	
	prt[16]='\0';
	i=(int)buf+len;
	while ((int)buf<i) {
		debmsg("%08x:\t",(int)buf);
		for (j=0;j<16 && (int)buf<i;j++) {
			prt[j]= isprint(*buf)? *buf:'_';
			debmsg("%02x ", *buf++);
		}
		prt[j]='\0';
		if (j<16) {
			char tabs[]="\0\0\0\0\0\0\0\0\0";
			memset(tabs,'\t',9-(16+3*(j+1))%8);
			debmsg(tabs);
		}
		debmsg("\t%s\n",prt);
	}
}

void char_out(unsigned char ch, char attr, int s)
{
	us *sadr, *p;

	if (s > 7) return;
	if (ch >= ' ') {
		sadr = SCREEN_ADR(s);
		sadr[ypos[s]*CO + xpos[s]++] = ch | (attr << 8);
		if (s == screen) outc(trans[ch]);
	} else if (ch == '\r') {
		xpos[s] = 0;
		if (s == screen) write(1, &ch, 1);
	} else if (ch == '\n') {
		ypos[s]++;
		if (s == screen) write(1, &ch, 1);
	} else if (ch == '\010' && xpos[s] > 0) {
		xpos[s]--;
		if (s == screen) write(1, &ch, 1);
	}
	if (xpos[s] == CO) {
		xpos[s] = 0;
		ypos[s]++;
	}
	if (ypos[s] == LI) {
		ypos[s]--;
		scrollup(0, 0, CO-1, LI-1, 1, 7);
	}
}

