xref: /inferno-os/os/boot/pc/cga.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 #include "u.h"
2 #include "lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 
7 enum {
8 	Width		= 160,
9 	Height		= 25,
10 
11 	Attr		= 7,		/* white on black */
12 };
13 
14 #define CGASCREENBASE	((uchar*)KADDR(0xB8000))
15 
16 static int pos;
17 static int screeninitdone;
18 
19 static uchar
cgaregr(int index)20 cgaregr(int index)
21 {
22 	outb(0x3D4, index);
23 	return inb(0x3D4+1) & 0xFF;
24 }
25 
26 static void
cgaregw(int index,int data)27 cgaregw(int index, int data)
28 {
29 	outb(0x3D4, index);
30 	outb(0x3D4+1, data);
31 }
32 
33 static void
movecursor(void)34 movecursor(void)
35 {
36 	cgaregw(0x0E, (pos/2>>8) & 0xFF);
37 	cgaregw(0x0F, pos/2 & 0xFF);
38 	CGASCREENBASE[pos+1] = Attr;
39 }
40 
41 static void
cgascreenputc(int c)42 cgascreenputc(int c)
43 {
44 	int i;
45 
46 	if(c == '\n'){
47 		pos = pos/Width;
48 		pos = (pos+1)*Width;
49 	}
50 	else if(c == '\t'){
51 		i = 8 - ((pos/2)&7);
52 		while(i-->0)
53 			cgascreenputc(' ');
54 	}
55 	else if(c == '\b'){
56 		if(pos >= 2)
57 			pos -= 2;
58 		cgascreenputc(' ');
59 		pos -= 2;
60 	}
61 	else{
62 		CGASCREENBASE[pos++] = c;
63 		CGASCREENBASE[pos++] = Attr;
64 	}
65 	if(pos >= Width*Height){
66 		memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
67 		memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
68 		pos = Width*(Height-1);
69 	}
70 	movecursor();
71 }
72 
73 static void
screeninit(void)74 screeninit(void)
75 {
76 	if(screeninitdone == 0){
77 		pos = cgaregr(0x0E)<<8;
78 		pos |= cgaregr(0x0F);
79 		pos *= 2;
80 		screeninitdone = 1;
81 	}
82 }
83 
84 void
cgascreenputs(char * s,int n)85 cgascreenputs(char* s, int n)
86 {
87 	if(screeninitdone == 0)
88 		screeninit();
89 	while(n-- > 0)
90 		cgascreenputc(*s++);
91 }
92