/* * Copyright 1982 UniSoft Corporation * Use of this material is subject to your disclosure agreement with * AT&T, Western Electric and UniSoft Corporation. * * Bitmap Display Driver * * The screen is 720 by 364 raster units.  A comfortable pixel size is * 9 by 10 giving 80 columns (9 wide) and 36 lines (10 deep).  The * extra 4 raster rows are unused.  Unfortunately this arrangement is * very expensive in processor time since pixels lie across byte boundaries. * * For the time being the pixel size used will be 8 by 9 providing a * screen area of 90 columns, and 40 lines. * * This is the low level display driver intended to simplify the task * of writing higher level screen emulators by simulating just the common * aspects of all crts in the following functions: * *	bminit ()		clears entire display *	bminvert (row, col)	invert character at row, column *	bmputc (r, c, char)	put the character at row, column *	bmwin (cmd, t, b, l, r) modifies window (top,bot,left,right); *				cmd == 1 means scroll up a line *				cmd == 0 means clear that area */#define FAST#define NODEBUG#include <sys/mmu.h>#include <sys/types.h>#include <sys/local.h>#include <sys/bmfont.h>char *bmscrn;		/* pointer to screen -- initialized in bminit */char bmcolor;		/* underline color; same as bmbck for no underlining */char bmbck;		/* current background color; 0 for white, -1 for black */char bmnormal;		/* normal background color; 0 for white, -1 for black */char bmfirst = 1;	/* is this the first boot? (not true for a restart) */bminit ()		/* one time screen initialization (called from mch.s) */{	register short i;		/* amount of screen in longs */	register long *p;	extern long bblank[];	*MEMEND -= SCRNSIZE;			/* lop off mem for screen */	bmscrn = *MEMEND;			/* logical screen address */	VIDADDR = ((int)(bmscrn+*MEMBASE)>>15);	/* init screen addr latch */	i = ((SCRNSIZE - (MAXCOL * MAXROW * V_RESO)) >> 2) - 1;	p = (long *)(bmscrn + (MAXCOL * MAXROW * V_RESO));	do {				/* so retrace lines won't show */		*p++ = -1;	} while (--i != -1);	bmcolor = 0;	/* bmcolor switches in bminit if bmbck is -1 */	bmbck = -1;	bmnormal = -1;	bmclear();	if (bmfirst) {		bmfirst = 0;		bmswitch();		bmclear();	} else {		bmcolor = -1;		for (i=0; i<16; i++)			bblank[i] = -1;		bmclear();	}}bmswitch(){	bmcolor = (bmcolor ? 0 : -1 );	bmifont();}bmifont()		/* invert the font table (set or reset rev. video) */{	register short i;		/* amount of screen in longs */	register char *f, g;	extern long bblank[];	i = sizeof(bmfont) - 1;	f = bmfont;	do {		g = ~*f;		*f++ = g;	}	while (--i != -1);	for (i=0; i<16; i++)		bblank[i] = ( bblank[i] ? 0 : -1);}bmsinv()		/* invert the entire screen */{	register short i;		/* amount of screen in chars */	register char *p, q;	i = MAXCOL * MAXROW * V_RESO;	p = bmscrn;	do {		q = ~*p;		*p++ = q;	} while (--i != 0);}#ifndef FAST/* Modify a section of the display * Cmd is 0 to clear the area, positive to scroll up that many lines * or negative to scroll down that many. */bmwin (cmd, tr, br, lc, rc)	short cmd, br, lc, rc;	register short tr;{	register short wrap, j, i;	short cols, rows;	register char *pc, *ec;	register char color = bmcolor;	pc = bmscrn;#ifndef NODEBUG	if (tr<0||tr>=MAXROW||br>=MAXCOL||br<tr	    ||lc<0||lc>=MAXCOL||rc>=MAXCOL||rc<=lc) {		printf("bmwin(%s,%d,%d,%d,%d) is illegal\n",			cmd?"scroll":"clear", tr, br, lc, rc);		return;	}#endif/* Calculate number of logical lines to operate on */	rows = br - tr + 1;/* Calculate number of columns (bytes) accross screen */	cols = rc - lc + 1;/* Wrap is an offset to be added to scan line pointers at the end of * each line to bring them around to the start of the next line. * It is the number of columns not being scrolled (usually zero) */	wrap = BPL - cols;		/* wrap around offset *//* Pc points at the upper area of the screen (ie, that which will * receive the scroll data). */	pc += tr * (short)(BPL * V_RESO) + lc;/* I is the number of scan lines to operate on.  ie. the number of * lines in the window minus the number of lines to scroll. */	i = (short)(rows - cmd) * (short)(V_RESO) - 1; /* scan lines *//* Here we do the scrolling if it is indicated */	if (cmd) {			/* scroll command lines *//* Ec is is set to point at the first line to scroll up */		ec = pc + cmd * ((short)(BPL) * (short)(V_RESO));		do {			/* scroll scan line at a time */			j = cols - 1;		/* column counter */			do *pc++ = *ec++;	/* optimizes to dbra loop */			while (--j != -1);			pc += wrap;		/* skip to next scan line */			ec += wrap;		} while (--i != -1);		i = (short)(V_RESO) * cmd - 1;	/* reset for clear */	}	do {			/* clear */		j = cols - 1;		do *pc++ = color;		while (--j != -1);		pc += wrap;	} while (--i != -1);	return;}#endifbminvert (r, c)			/* reverse video char under cursor */	register short r, c;{	register char *p = bmscrn;	register short i;	p += (r * (BPL * V_RESO)) + c;	i = V_RESO;	do {		*p = ~*p;		p += BPL;		/* 1 scan line */	} while (--i != 0);}		bmmvc (dr, dc, sr, sc)			/* copy char at (sr,sc) to (dr,dc) */register short dr, dc;register short sr, sc;{	register char *dest, *src;	register short i;	dest = bmscrn + (dr * (BPL * V_RESO)) + dc;	src = bmscrn + (sr * (BPL * V_RESO)) + sc;	i = V_RESO;	do {		*dest = *src;		dest += BPL;		/* 1 scan line */		src += BPL;		/* 1 scan line */	} while (--i != 0);}#ifndef FASTbmcpl(dl, sl)				/* copy line sl to dl */register dl, sl;{	register char *dest, *src;	register short i;	dest = bmscrn + (dl * (BPL * V_RESO));	src = bmscrn + (sl * (BPL * V_RESO));	i = BPL * V_RESO;	do {		*dest = *src;		dest++;			/* 1 scan line */		src++;			/* 1 scan line */	} while (--i != 0);}#else FASTbmcpl(dl, sl)				/* copy line sl to dl */register dl, sl;{	register char *dest, *src;	dest = bmscrn + (dl * (BPL * V_RESO));	/* register a5 */	src = bmscrn + (sl * (BPL * V_RESO));	/* register a4 */	/* Use the 13 registers a6, a3-a0 and d7-d0 to copy 52 bytes at a time. */	asm(" moveml	#0xFFFF,sp@- ");	/* save all the registers */	asm(" moveml	a4@,#0x4FFF ");		/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@ ");	asm(" moveml	a4@(52),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(52) ");	asm(" moveml	a4@(104),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(104) ");	asm(" moveml	a4@(156),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(156) ");	asm(" moveml	a4@(208),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(208) ");	asm(" moveml	a4@(260),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(260) ");	asm(" moveml	a4@(312),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(312) ");	asm(" moveml	a4@(364),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(364) ");	asm(" moveml	a4@(416),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(416) ");	asm(" moveml	a4@(468),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(468) ");	asm(" moveml	a4@(520),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(520) ");	asm(" moveml	a4@(572),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(572) ");	asm(" moveml	a4@(624),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(624) ");	asm(" moveml	a4@(676),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(676) ");	asm(" moveml	a4@(728),#0x4FFF ");	/* move 52 bytes */	asm(" moveml	#0x4FFF,a5@(728) ");	asm(" moveml	a4@(780),#0x7F ");	/* move 28 more bytes */	asm(" moveml	#0x7F,a5@(780) ");	asm(" movw	a4@(808),a5@(808) ");	/* move last 2 bytes */	asm(" moveml	sp@+,#0xFFFF ");#ifdef lint	if (dest)		return;	else if (src)		return;#endif lint}#endif FAST#ifndef FASTbmblank(dl)				/* blank line dl */register dl;{	register char *dest;	register short i;	dest = bmscrn + (dl * (BPL * V_RESO));	i = BPL * V_RESO;	do {		*dest = bmnormal;		dest++;			/* 1 scan line */	} while (--i != 0);}#else FASTbmblank(dl)				/* blank line dl */register dl;{	register char *dest, *a4;	/* NOTUSED */	extern long bblank[];	dest = bmscrn + (dl * (BPL * V_RESO));	/* register a5 */	asm(" moveml	#0xFFFF,sp@- ");	/* save all the registers */	a4 = (char *)bblank;	asm(" moveml	a4@,#0x4FFF ");		/* set a6,a3-a0,d7-d0 to blanks */	asm(" movl	a6,a4 ");		/* set a4 to blanks */	asm(" moveml	#0x5FFF,a5@ ");		/* move 56 bytes */	asm(" moveml	#0x5FFF,a5@(56) ");	asm(" moveml	#0x5FFF,a5@(112) ");	asm(" moveml	#0x5FFF,a5@(168) ");	asm(" moveml	#0x5FFF,a5@(224) ");	asm(" moveml	#0x5FFF,a5@(280) ");	asm(" moveml	#0x5FFF,a5@(336) ");	asm(" moveml	#0x5FFF,a5@(392) ");	asm(" moveml	#0x5FFF,a5@(448) ");	asm(" moveml	#0x5FFF,a5@(504) ");	asm(" moveml	#0x5FFF,a5@(560) ");	asm(" moveml	#0x5FFF,a5@(616) ");	asm(" moveml	#0x5FFF,a5@(672) ");	asm(" moveml	#0x5FFF,a5@(728) ");	asm(" moveml	#0x3F,a5@(784) ");	/* move another 24 bytes */	asm(" movw	_bblank,a5@(808) ");	/* move last 2 bytes */	asm(" moveml	sp@+,#0xFFFF ");#ifdef lint	if (dest)		return;	else if (a4)		return;#endif lint}#endif FASTbmputc (r, c, k)			/* draw a char at location r, c */	register short r, c;	char k;{	register char *p = bmscrn;	register char *f = &bmfont[0];	register short i;#ifndef NODEBUG	if (r < 0 || c < 0 || r >= MAXROW || c >= MAXCOL) {		printf("bmputc(%d, %d, `%c') is illegal\n",r,c,k);		return;	}#endif	p += (r * (BPL * V_RESO)) + c;	f += (k - ' ') << 3;	i = FONTVERT - 1;		/* bytes in font table for one char */	do {		*p = *f++;		p += BPL;		/* 1 scan line == 90 bytes */	} while (--i != -1);	*p = bmcolor;			/* blank row under cursor */}long bblank[16];int savesp;bmclear(){	int x;#ifdef lint	savesp++;#endif	x = spl7();	asm(" moveml	#0xFFFF,sp@- ");	asm(" movl	sp,_savesp ");	asm(" moveml	_bblank,#0xFFFF ");	asm(" movl	_bmscrn,sp ");	asm(" addl	#32400,sp ");	asm("1$: moveml	#0xFFFE,sp@- ");	asm(" moveml	#0xFFFE,sp@- ");	asm(" moveml	#0xFFFE,sp@- ");	asm(" moveml	#0xFFFE,sp@- ");	asm(" moveml	#0xFFFE,sp@- ");	asm(" moveml	#0xFFFE,sp@- ");	asm(" moveml	#0xFFFE,sp@- ");	asm(" moveml	#0xFFFE,sp@- ");	asm(" moveml	#0xFFFE,sp@- ");	asm(" moveml	#0xFFFE,sp@- ");	asm(" cmpl	_bmscrn,sp ");	asm(" bne	1$ ");	asm(" movl	_savesp,sp ");	asm(" moveml	sp@+,#0xFFFF ");	splx(x);}#ifndef FASTbmrscrl(){	register i = 29969;	register char *dest, *src;	dest = bmscrn+30779;	src = bmscrn+29969;	do {		*dest-- = *src--;	} while (--i != -1);}#else FAST/* * move 37 lines of 9 lines of pixels times 90 columns * which is 29970 bytes to bmscrn+29970 from * bmscrn+ 30780 * use all of the registers except a6,a5,d0 and a7 */bmrscrl(){	asm(" moveml	#0xFFFF,sp@- ");	/* save all the registers */	asm(" movl	_bmscrn,a6 ");	asm(" movl	_bmscrn,a5 ");	asm(" addl	#30732,a5 ");		/* destination - 48 bytes */	asm(" addl	#29922,a6 ");		/* source - 48 bytes */	asm(" movl	#77,d0 ");		/* 77 times -1 */	asm("1$: moveml	a6@,#0x1FFE ");	asm(" moveml	#0x1FFE,a5@ ");	asm(" moveml	a6@(-48),#0x1FFE ");	asm(" moveml	#0x1FFE,a5@(-48) ");	asm(" moveml	a6@(-96),#0x1FFE ");	asm(" moveml	#0x1FFE,a5@(-96) ");	asm(" moveml	a6@(-144),#0x1FFE ");	asm(" moveml	#0x1FFE,a5@(-144) ");	asm(" moveml	a6@(-192),#0x1FFE ");	asm(" moveml	#0x1FFE,a5@(-192) ");	asm(" moveml	a6@(-240),#0x1FFE ");	asm(" moveml	#0x1FFE,a5@(-240) ");	asm(" moveml	a6@(-288),#0x1FFE ");	asm(" moveml	#0x1FFE,a5@(-288) ");	asm(" moveml	a6@(-336),#0x1FFE ");	asm(" moveml	#0x1FFE,a5@(-336) ");	asm(" subw 	#384,a6 ");	asm(" subw 	#384,a5 ");	asm(" dbra	d0,1$ ");	asm(" moveml	a6@(32),#0x1E ");	/* move 16 more bytes) */	asm(" moveml	#0x1E,a5@(32) ");	asm(" movw	a6@(30),a5@(30) ");	asm(" moveml	sp@+,#0xFFFF ");}#endif FAST