1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7
8 #define Image IMAGE
9 #include <draw.h>
10 #include <memdraw.h>
11 #include <cursor.h>
12 #include "screen.h"
13
14 static Memimage* back;
15 static Memimage *conscol;
16
17 static Point curpos;
18 static Rectangle window;
19 static int *xp;
20 static int xbuf[256];
21 static Lock vgascreenlock;
22 int drawdebug;
23
24 void
vgaimageinit(ulong chan)25 vgaimageinit(ulong chan)
26 {
27 if(back == nil){
28 back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
29 if(back == nil)
30 panic("back alloc"); /* RSC BUG */
31 back->flags |= Frepl;
32 back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
33 memfillcolor(back, DBlack);
34 }
35
36 if(conscol == nil){
37 conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
38 if(conscol == nil)
39 panic("conscol alloc"); /* RSC BUG */
40 conscol->flags |= Frepl;
41 conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
42 memfillcolor(conscol, DWhite);
43 }
44 }
45
46 static void
vgascroll(VGAscr * scr)47 vgascroll(VGAscr* scr)
48 {
49 int h, o;
50 Point p;
51 Rectangle r;
52
53 h = scr->memdefont->height;
54 o = 8*h;
55 r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
56 p = Pt(window.min.x, window.min.y+o);
57 memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S);
58 r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
59 memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
60
61 curpos.y -= o;
62 }
63
64 static void
vgascreenputc(VGAscr * scr,char * buf,Rectangle * flushr)65 vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
66 {
67 Point p;
68 int h, w, pos;
69 Rectangle r;
70
71 // drawdebug = 1;
72 if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
73 xp = xbuf;
74
75 h = scr->memdefont->height;
76 switch(buf[0]){
77
78 case '\n':
79 if(curpos.y+h >= window.max.y){
80 vgascroll(scr);
81 *flushr = window;
82 }
83 curpos.y += h;
84 vgascreenputc(scr, "\r", flushr);
85 break;
86
87 case '\r':
88 xp = xbuf;
89 curpos.x = window.min.x;
90 break;
91
92 case '\t':
93 p = memsubfontwidth(scr->memdefont, " ");
94 w = p.x;
95 if(curpos.x >= window.max.x-4*w)
96 vgascreenputc(scr, "\n", flushr);
97
98 pos = (curpos.x-window.min.x)/w;
99 pos = 4-(pos%4);
100 *xp++ = curpos.x;
101 r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
102 memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
103 curpos.x += pos*w;
104 break;
105
106 case '\b':
107 if(xp <= xbuf)
108 break;
109 xp--;
110 r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
111 memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S);
112 combinerect(flushr, r);
113 curpos.x = *xp;
114 break;
115
116 case '\0':
117 break;
118
119 default:
120 p = memsubfontwidth(scr->memdefont, buf);
121 w = p.x;
122
123 if(curpos.x >= window.max.x-w)
124 vgascreenputc(scr, "\n", flushr);
125
126 *xp++ = curpos.x;
127 r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
128 memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
129 memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
130 combinerect(flushr, r);
131 curpos.x += w;
132 }
133 // drawdebug = 0;
134 }
135
136 static void
vgascreenputs(char * s,int n)137 vgascreenputs(char* s, int n)
138 {
139 int i;
140 Rune r;
141 char buf[4];
142 VGAscr *scr;
143 Rectangle flushr;
144
145 scr = &vgascreen[0];
146
147 if(!islo()){
148 /*
149 * Don't deadlock trying to
150 * print in an interrupt.
151 */
152 if(!canlock(&vgascreenlock))
153 return;
154 }
155 else
156 lock(&vgascreenlock);
157
158 flushr = Rect(10000, 10000, -10000, -10000);
159
160 while(n > 0){
161 i = chartorune(&r, s);
162 if(i == 0){
163 s++;
164 --n;
165 continue;
166 }
167 memmove(buf, s, i);
168 buf[i] = 0;
169 n -= i;
170 s += i;
171 vgascreenputc(scr, buf, &flushr);
172 }
173 flushmemscreen(flushr);
174
175 unlock(&vgascreenlock);
176 }
177
178 void
vgascreenwin(VGAscr * scr)179 vgascreenwin(VGAscr* scr)
180 {
181 int h, w;
182
183 h = scr->memdefont->height;
184 w = scr->memdefont->info[' '].width;
185
186 window = insetrect(scr->gscreen->r, 48);
187 window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w;
188 window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
189 curpos = window.min;
190
191 screenputs = vgascreenputs;
192 }
193
194 /*
195 * Supposedly this is the way to turn DPMS
196 * monitors off using just the VGA registers.
197 * Unfortunately, it seems to mess up the video mode
198 * on the cards I've tried.
199 */
200 void
vgablank(VGAscr *,int blank)201 vgablank(VGAscr*, int blank)
202 {
203 uchar seq1, crtc17;
204
205 if(blank) {
206 seq1 = 0x00;
207 crtc17 = 0x80;
208 } else {
209 seq1 = 0x20;
210 crtc17 = 0x00;
211 }
212
213 outs(Seqx, 0x0100); /* synchronous reset */
214 seq1 |= vgaxi(Seqx, 1) & ~0x20;
215 vgaxo(Seqx, 1, seq1);
216 crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
217 delay(10);
218 vgaxo(Crtx, 0x17, crtc17);
219 outs(Crtx, 0x0300); /* end synchronous reset */
220 }
221
222 void
cornerstring(char * s)223 cornerstring(char *s)
224 {
225 int h, w;
226 VGAscr *scr;
227 Rectangle r;
228 Point p;
229
230 scr = &vgascreen[0];
231 if(scr->aperture == 0 || screenputs != vgascreenputs)
232 return;
233 p = memsubfontwidth(scr->memdefont, s);
234 w = p.x;
235 h = scr->memdefont->height;
236
237 r = Rect(0, 0, w, h);
238 memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
239 memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s);
240 // flushmemscreen(r);
241 }
242