video.h

#include 
#define begin {
#define end   }

char screen[1600];

//NOTE that v1 to v8 and i must be in registers!
register char v1 @4;
register char v2 @5;
register char v3 @6;
register char v4 @7;
register char v5 @8;
register char v6 @9;
register char v7 @10;
register char v8 @11;
register int i @12;

flash char pos[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

//define some character bitmaps
//5x7 characters
flash char bitmap[39][7]={
	//0
	0b01110000,
	0b10001000,
	0b10011000,
	0b10101000,
	0b11001000,
	0b10001000,
	0b01110000,
	//1
	0b00100000,
	0b01100000,
	0b00100000,
	0b00100000,
	0b00100000,
	0b00100000,
	0b01110000,
	//2
	0b01110000,
	0b10001000,
	0b00001000,
	0b00010000,
	0b00100000,
	0b01000000,
	0b11111000,
    //3
	0b11111000,
	0b00010000,
	0b00100000,
	0b00010000,
	0b00001000,
	0b10001000,
	0b01110000,
	//4
	0b00010000,
	0b00110000,
	0b01010000,
	0b10010000,
	0b11111000,
	0b00010000,
	0b00010000,
	//5
	0b11111000,
	0b10000000,
	0b11110000,
	0b00001000,
	0b00001000,
	0b10001000,
	0b01110000,
	//6
	0b01000000,
	0b10000000,
	0b10000000,
	0b11110000,
	0b10001000,
	0b10001000,
	0b01110000,
	//7
	0b11111000,
	0b00001000,
	0b00010000,
	0b00100000,
	0b01000000,
	0b10000000,
	0b10000000,
	//8
	0b01110000,
	0b10001000,
	0b10001000,
	0b01110000,
	0b10001000,
	0b10001000,
	0b01110000,
	//9
	0b01110000,
	0b10001000,
	0b10001000,
	0b01111000,
	0b00001000,
	0b00001000,
	0b00010000,
	//A
	0b01110000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b11111000,
	0b10001000,
	0b10001000,
	//B
	0b11110000,
	0b10001000,
	0b10001000,
	0b11110000,
	0b10001000,
	0b10001000,
	0b11110000,
	//C
	0b01110000,
	0b10001000,
	0b10000000,
	0b10000000,
	0b10000000,
	0b10001000,
	0b01110000,
	//D
	0b11110000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b11110000,
	//E
	0b11111000,
	0b10000000,
	0b10000000,
	0b11111000,
	0b10000000,
	0b10000000,
	0b11111000,
	//F
	0b11111000,
	0b10000000,
	0b10000000,
	0b11111000,
	0b10000000,
	0b10000000,
	0b10000000,
	//G
	0b01110000,
	0b10001000,
	0b10000000,
	0b10011000,
	0b10001000,
	0b10001000,
	0b01110000,
	//H
	0b10001000,
	0b10001000,
	0b10001000,
	0b11111000,
	0b10001000,
	0b10001000,
	0b10001000,
	//I
	0b01110000,
	0b00100000,
	0b00100000,
	0b00100000,
	0b00100000,
	0b00100000,
	0b01110000,
	//J
	0b00111000,
	0b00010000,
	0b00010000,
	0b00010000,
	0b00010000,
	0b10010000,
	0b01100000,
	//K
	0b10001000,
	0b10010000,
	0b10100000,
	0b11000000,
	0b10100000,
	0b10010000,
	0b10001000,
	//L
	0b10000000,
	0b10000000,
	0b10000000,
	0b10000000,
	0b10000000,
	0b10000000,
	0b11111000,
	//M
	0b10001000,
	0b11011000,
	0b10101000,
	0b10101000,
	0b10001000,
	0b10001000,
	0b10001000,
	//N
	0b10001000,
	0b10001000,
	0b11001000,
	0b10101000,
	0b10011000,
	0b10001000,
	0b10001000,
	//O
	0b01110000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b01110000,
	//P
	0b11110000,
	0b10001000,
	0b10001000,
	0b11110000,
	0b10000000,
	0b10000000,
	0b10000000,
	//Q
	0b01110000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b10101000,
	0b10010000,
	0b01101000,
	//R
	0b11110000,
	0b10001000,
	0b10001000,
	0b11110000,
	0b10100000,
	0b10010000,
	0b10001000,
	//S
	0b01111000,
	0b10000000,
	0b10000000,
	0b01110000,
	0b00001000,
	0b00001000,
	0b11110000,
	//T
	0b11111000,
	0b00100000,
	0b00100000,
	0b00100000,
	0b00100000,
	0b00100000,
	0b00100000,
	//U
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b01110000,
	//V
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b01010000,
	0b00100000,
	//W
	0b10001000,
	0b10001000,
	0b10001000,
	0b10101000,
	0b10101000,
	0b10101000,
	0b01010000,
	//X
	0b10001000,
	0b10001000,
	0b01010000,
	0b00100000,
	0b01010000,
	0b10001000,
	0b10001000,
	//Y
	0b10001000,
	0b10001000,
	0b10001000,
	0b01010000,
	0b00100000,
	0b00100000,
	0b00100000,
	//Z
	0b11111000,
	0b00001000,
	0b00010000,
	0b00100000,
	0b01000000,
	0b10000000,
	0b11111000,
	 //.
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	0b00111000,
	0b00111000,
	//blank
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	//figure2
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000
	};


//================================
//3x5 font numbers, then letters
//packed two per definition for fast
//copy to the screen at x-position divisible by 4
flash char smallbitmap[39][5]={
	//0
    0b11101110,
	0b10101010,
	0b10101010,
	0b10101010,
	0b11101110,
	//1
	0b01000100,
	0b11001100,
	0b01000100,
	0b01000100,
	0b11101110,
	//2
	0b11101110,
	0b00100010,
	0b11101110,
	0b10001000,
	0b11101110,
	//3
	0b11101110,
	0b00100010,
	0b11101110,
	0b00100010,
	0b11101110,
	//4
	0b10101010,
	0b10101010,
	0b11101110,
	0b00100010,
	0b00100010,
	//5
	0b11101110,
	0b10001000,
	0b11101110,
	0b00100010,
	0b11101110,
	//6
	0b11001100,
	0b10001000,
	0b11101110,
	0b10101010,
	0b11101110,
	//7
	0b11101110,
	0b00100010,
	0b01000100,
	0b10001000,
	0b10001000,
	//8
	0b11101110,
	0b10101010,
	0b11101110,
	0b10101010,
	0b11101110,
	//9
	0b11101110,
	0b10101010,
	0b11101110,
	0b00100010,
	0b01100110,
	//:
	0b00000000,
	0b01000100,
	0b00000000,
	0b01000100,
	0b00000000,
	//=
	0b00000000,
	0b11101110,
	0b00000000,
	0b11101110,
	0b00000000,
	//blank
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	0b00000000,
	//A
	0b11101110,
	0b10101010,
	0b11101110,
	0b10101010,
	0b10101010,
	//B
	0b11001100,
	0b10101010,
	0b11101110,
	0b10101010,
	0b11001100,
	//C
	0b11101110,
	0b10001000,
	0b10001000,
	0b10001000,
	0b11101110,
	//D
	0b11001100,
	0b10101010,
	0b10101010,
	0b10101010,
	0b11001100,
	//E
	0b11101110,
	0b10001000,
	0b11101110,
	0b10001000,
	0b11101110,
	//F
	0b11101110,
	0b10001000,
	0b11101110,
	0b10001000,
	0b10001000,
	//G
	0b11101110,
	0b10001000,
	0b10001000,
	0b10101010,
	0b11101110,
	//H
	0b10101010,
	0b10101010,
	0b11101110,
	0b10101010,
	0b10101010,
	//I
	0b11101110,
	0b01000100,
	0b01000100,
	0b01000100,
	0b11101110,
	//J
	0b00100010,
	0b00100010,
	0b00100010,
	0b10101010,
	0b11101110,
	//K
	0b10001000,
	0b10101010,
	0b11001100,
	0b11001100,
	0b10101010,
	//L
	0b10001000,
	0b10001000,
	0b10001000,
	0b10001000,
	0b11101110,
	//M
	0b10101010,
	0b11101110,
	0b11101110,
	0b10101010,
	0b10101010,
	//N
	0b00000000,
	0b11001100,
	0b10101010,
	0b10101010,
	0b10101010,
	//O
	0b01000100,
	0b10101010,
	0b10101010,
	0b10101010,
	0b01000100,
	//P
	0b11101110,
	0b10101010,
	0b11101110,
	0b10001000,
	0b10001000,
	//Q
	0b01000100,
	0b10101010,
	0b10101010,
	0b11101110,
	0b01100110,
	//R
	0b11101110,
	0b10101010,
	0b11001100,
	0b11101110,
	0b10101010,
	//S
	0b11101110,
	0b10001000,
	0b11101110,
	0b00100010,
	0b11101110,
	//T
	0b11101110,
	0b01000100,
	0b01000100,
	0b01000100,
	0b01000100,
	//U
	0b10101010,
	0b10101010,
	0b10101010,
	0b10101010,
	0b11101110,
	//V
	0b10101010,
	0b10101010,
	0b10101010,
	0b10101010,
	0b01000100,
	//W
	0b10101010,
	0b10101010,
	0b11101110,
	0b11101110,
	0b10101010,
	//X
	0b00000000,
	0b10101010,
	0b01000100,
	0b01000100,
	0b10101010,
	//Y
	0b10101010,
	0b10101010,
	0b01000100,
	0b01000100,
	0b01000100,
	//Z
	0b11101110,
	0b00100010,
	0b01000100,
	0b10001000,
	0b11101110
	};

//==================================
//plot one point
//at x,y with color 1=white 0=black 2=invert
#pragma warn-
void video_pt(char x, char y, char c)
begin

	#asm
	;  i=(x>>3) + ((int)y<<4) ;   the byte with the pixel in it

	push r16
	ldd r30,y+2 		;get x
	lsr r30
	lsr r30
	lsr r30     		;divide x by 8
	ldd r12,y+1 		;get y
       	lsl r12     		;mult y by 16
       	clr r13
	lsl r12
	rol r13
	lsl r12
	rol r13
	lsl r12
	rol r13
	add r12, r30     	;add in x/8

	;v2 = screen[i];   r5
        ;v3 = pos[x & 7];  r6
	;v4 = c            r7
	ldi r30,low(_screen)
	ldi r31,high(_screen)
	add r30, r12
	adc r31, r13
	ld r5,Z  		;get screen byte
	ldd r26,y+2 		;get x
	ldi r27,0
	andi r26,0x07           ;form x & 7
	ldi r30,low(_pos*2)
	ldi r31,high(_pos*2)
	add r30,r26
	adc r31,r27
	lpm r6,Z
	ld r16,y 		;get c

       ;if (v4==1) screen[i] = v2 | v3 ;
       ;if (v4==0) screen[i] = v2 & ~v3;
       ;if (v4==2) screen[i] = v2 ^ v3 ;

       cpi r16,1
       brne tst0
       or  r5,r6
       tst0:
       cpi r16,0
       brne tst2
       com r6
       and r5,r6
       tst2:
       cpi r16,2
       brne writescrn
       eor r5,r6
       writescrn:
       	ldi r30,low(_screen)
	ldi r31,high(_screen)
	add r30, r12
	adc r31, r13
	st Z, r5        	;write the byte back to the screen

	pop r16
	#endasm

end
#pragma warn+

//==================================
// put a big character on the screen
// c is index into bitmap
void video_putchar(char x, char y, char c)
begin
    v7 = x;
    for (v6=0;v6<7;v6++)
    begin
        v1 = bitmap[c][v6];
        v8 = y+v6;
        video_pt(v7,   v8, (v1 & 0x80)==0x80);
        video_pt(v7+1, v8, (v1 & 0x40)==0x40);
        video_pt(v7+2, v8, (v1 & 0x20)==0x20);
        video_pt(v7+3, v8, (v1 & 0x10)==0x10);
        video_pt(v7+4, v8, (v1 & 0x08)==0x08);
    end
end

//==================================
// put a string of big characters on the screen
void video_puts(char x, char y, char *str)
begin
	char i ;
	for (i=0; str[i]!=0; i++)
	begin
		if (str[i]>=0x30 && str[i]<=0x3a)
			video_putchar(x,y,str[i]-0x30);
		else if   (str[i]==0x2E)
			video_putchar(x,y,36);
		else video_putchar(x,y,str[i]-0x40+9);
		x = x+6;
	end
end

//==================================
// put a small character on the screen
// x-cood must be on divisible by 4
// c is index into bitmap
void video_smallchar(char x, char y, char c)
begin
	char mask;
	i=((int)x>>3) + ((int)y<<4) ;
	if (x == (x & 0xf8)) mask = 0x0f;     //f8
	else mask = 0xf0;

	screen[i] =    (screen[i] & mask) | (smallbitmap[c][0] & ~mask);
   	screen[i+16] = (screen[i+16] & mask) | (smallbitmap[c][1] & ~mask);
        screen[i+32] = (screen[i+32] & mask) | (smallbitmap[c][2] & ~mask);
        screen[i+48] = (screen[i+48] & mask) | (smallbitmap[c][3] & ~mask);
   	screen[i+64] = (screen[i+64] & mask) | (smallbitmap[c][4] & ~mask);
end

//==================================
// put a string of small characters on the screen
// x-cood must be on divisible by 4
void video_putsmalls(char x, char y, char *str)
begin
	char i ;
	for (i=0; str[i]!=0; i++)
	begin
		if (str[i]>=0x30 && str[i]<=0x3a)
			video_smallchar(x,y,str[i]-0x30);
		else video_smallchar(x,y,str[i]-0x40+12);
		x = x+4;
	end
end

//==================================
//plot a line
//at x1,y1 to x2,y2 with color 1=white 0=black 2=invert
//NOTE: this function requires signed chars
//Code is from David Rodgers,
//"Procedural Elements of Computer Graphics",1985
void video_line(char x1, char y1, char x2, char y2, char c)
begin
	int e;
	signed char dx,dy,j, temp;
	signed char s1,s2, xchange;
        signed char x,y;

	x = x1;
	y = y1;
	dx = cabs(x2-x1);
	dy = cabs(y2-y1);
	s1 = csign(x2-x1);
	s2 = csign(y2-y1);
	xchange = 0;
	if (dy>dx)
	begin
		temp = dx;
		dx = dy;
		dy = temp;
		xchange = 1;
	end
	e = ((int)dy<<1) - dx;
	for (j=0; j<=dx; j++)
	begin
		video_pt(x,y,c) ;
		if (e>=0)
		begin
			if (xchange==1) x = x + s1;
			else y = y + s2;
			e = e - ((int)dx<<1);
		end
		if (xchange==1) y = y + s2;
		else x = x + s1;
		e = e + ((int)dy<<1);
	end
end

//==================================
//return the value of one point
//at x,y with color 1=white 0=black 2=invert
char video_set(char x, char y)
begin
	//The following construction
  	//detects exactly one bit at the x,y location
	i=((int)x>>3) + ((int)y<<4) ;
    return ( screen[i] & 1<<(7-(x & 0x7)));
end