1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "io.h" 5 #include "dat.h" 6 #include "fns.h" 7 #include "../port/error.h" 8 9 #include <draw.h> 10 #include <memdraw.h> 11 #include <memlayer.h> 12 #include <cursor.h> 13 14 #include "softcursor.h" 15 #include "screen.h" 16 17 #define Backgnd (0xFF) 18 19 20 ulong consbits = 0xC0; 21 Memdata consdata = { 22 nil, 23 &consbits 24 }; 25 Memimage conscol = 26 { 27 { 0, 0, 1, 1 }, 28 { -100000, -100000, 100000, 100000 }, 29 3, 30 1, 31 &consdata, 32 0, 33 1 34 }; 35 36 ulong onesbits = ~0; 37 Memdata onesdata = { 38 nil, 39 &onesbits, 40 }; 41 Memimage xones = 42 { 43 { 0, 0, 1, 1 }, 44 { -100000, -100000, 100000, 100000 }, 45 3, 46 1, 47 &onesdata, 48 0, 49 1 50 }; 51 Memimage *memones = &xones; 52 53 ulong zerosbits = 0; 54 Memdata zerosdata = { 55 nil, 56 &zerosbits, 57 }; 58 Memimage xzeros = 59 { 60 { 0, 0, 1, 1 }, 61 { -100000, -100000, 100000, 100000 }, 62 3, 63 1, 64 &zerosdata, 65 0, 66 1 67 }; 68 Memimage *memzeros = &xzeros; 69 70 ulong backbits = (Backgnd<<24)|(Backgnd<<16)|(Backgnd<<8)|Backgnd; 71 Memdata backdata = { 72 nil, 73 &backbits 74 }; 75 Memimage xback = 76 { 77 { 0, 0, 1, 1 }, 78 { -100000, -100000, 100000, 100000 }, 79 3, 80 1, 81 &backdata, 82 0, 83 1 84 }; 85 Memimage *back = &xback; 86 87 Video *vid; 88 static Memsubfont *memdefont; 89 static Lock screenlock; 90 Memimage gscreen; 91 Memdata gscreendata; 92 static Point curpos; 93 static Rectangle window; 94 95 static Vctlr* vctlr; 96 97 static Cursor arrow = { 98 { -1, -1 }, 99 { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C, 100 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, 101 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04, 102 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40, 103 }, 104 { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0, 105 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8, 106 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8, 107 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00, 108 }, 109 }; 110 111 112 void 113 graphicscmap(int invert) 114 { 115 int num, den, i, j; 116 int r, g, b, cr, cg, cb, v; 117 118 if(vctlr->setcolor == nil) 119 return; 120 121 for(r=0,i=0;r!=4;r++) for(v=0;v!=4;v++,i+=16){ 122 for(g=0,j=v-r;g!=4;g++) for(b=0;b!=4;b++,j++){ 123 den=r; 124 if(g>den) den=g; 125 if(b>den) den=b; 126 if(den==0) /* divide check -- pick grey shades */ 127 cr=cg=cb=v*17; 128 else{ 129 num=17*(4*den+v); 130 cr=r*num/den; 131 cg=g*num/den; 132 cb=b*num/den; 133 } 134 if(invert) 135 vctlr->setcolor(255-i-(j&15), 136 cr*0x01010101, 137 cg*0x01010101, 138 cb*0x01010101); 139 else 140 vctlr->setcolor(i+(j&15), 141 cr*0x01010101, 142 cg*0x01010101, 143 cb*0x01010101); 144 } 145 } 146 } 147 148 static char s1[] = 149 { 150 0x00, 0x00, 0xC0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 151 }; 152 153 154 void 155 dacinit(void) 156 { 157 int i; 158 159 /* Control registers */ 160 vid->addr = 0x01 << 24; 161 vid->color = 0x02 << 24; 162 for(i = 0; i < sizeof s1; i++) 163 vid->cntrl = s1[i] << 24; 164 165 /* Cursor programming */ 166 vid->addr = 0x00 << 24; 167 vid->color = 0x03 << 24; 168 vid->cntrl = 0xC0 << 24; 169 for(i = 0; i < 12; i++) 170 vid->cntrl = 0 << 24; 171 172 /* Load Cursor Ram */ 173 vid->addr = 0x00 << 24; 174 vid->color = 0x04 << 24; 175 for(i = 0; i < 0x400; i++) 176 vid->cntrl = 0xff << 24; 177 178 graphicscmap(1); 179 180 /* Overlay Palette Ram */ 181 vid->addr = 0x00 << 24; 182 vid->color = 0x01 << 24; 183 for(i = 0; i < 0x10; i++) { 184 vid->cntrl = 0xff << 24; 185 vid->cntrl = 0xff << 24; 186 vid->cntrl = 0xff << 24; 187 } 188 189 /* Overlay Palette Ram */ 190 vid->addr = 0x81; 191 vid->color = 0x01; 192 for(i = 0; i < 3; i++) { 193 vid->cntrl = 0xff << 24; 194 vid->cntrl = 0xff << 24; 195 vid->cntrl = 0xff << 24; 196 } 197 } 198 199 void 200 vctlrinit(int x, int y, int d) 201 { 202 int h; 203 ulong va; 204 205 if(vctlr == nil){ 206 /* 207 * find a controller somehow 208 * and call its init routine 209 */ 210 extern Vctlr FSV; 211 212 vctlr = FSV.init(0, x, y, d); 213 vctlr->load(&arrow); 214 } 215 216 if(vctlr == nil) 217 panic("%s",Ebadarg); 218 219 gscreen.data = &gscreendata; 220 gscreen.r.min = Pt(0, 0); 221 gscreen.r.max = Pt(vctlr->x, vctlr->y); 222 gscreen.clipr = gscreen.r; 223 gscreen.ldepth = vctlr->d; 224 gscreen.repl = 0; 225 va = kmapsbus(FSVSLOT); /* FSV is in slot 2 */ 226 gscreendata.data = (ulong *)(va+0x800000); /* Framebuffer Magic */ 227 gscreen.width = (vctlr->x *(1<<gscreen.ldepth)+31)/32; 228 229 230 h = memdefont->height; 231 232 vid = (Video*)(va+0x240000); /* RAMDAC Magic */ 233 memset(gscreendata.data, Backgnd, vctlr->x*vctlr->y); 234 window = gscreen.r; 235 window.max.x = vctlr->x; 236 window.max.y = (vctlr->y/h) * h; 237 curpos = window.min; 238 if (gscreen.ldepth == 3){ 239 dacinit(); 240 } 241 242 memset(gscreendata.data, Backgnd, vctlr->x*vctlr->y); 243 window = gscreen.r; 244 window.max.x = vctlr->x; 245 window.max.y = (vctlr->y/h) * h; 246 curpos = window.min; 247 } 248 249 void 250 screeninit(void) 251 { 252 memdefont = getmemdefont(); 253 vctlrinit(1024, 768, 3); 254 } 255 256 ulong* 257 attachscreen(Rectangle *r, int *ld, int *width, int *softscreen) 258 { 259 *r = gscreen.r; 260 *ld = gscreen.ldepth; 261 *width = gscreen.width; 262 *softscreen = 0; 263 return gscreendata.data; 264 } 265 266 void 267 detachscreen(void) 268 { 269 } 270 271 void 272 flushmemscreen(Rectangle) 273 { 274 } 275 276 static void 277 scroll(void) 278 { 279 int o; 280 Point p; 281 Rectangle r; 282 283 o = 4*memdefont->height; 284 r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); 285 p = Pt(window.min.x, window.min.y+o); 286 memdraw(&gscreen, r, &gscreen, p, memones, p); 287 r = Rpt(Pt(window.min.x, window.max.y-o), window.max); 288 memdraw(&gscreen, r, back, memzeros->r.min, memones, memzeros->r.min); 289 290 curpos.y -= o; 291 } 292 293 void 294 screenputc(char *buf) 295 { 296 Point p; 297 int h, w, pos; 298 Rectangle r; 299 static int *xp; 300 static int xbuf[256]; 301 302 h = memdefont->height; 303 if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) 304 xp = xbuf; 305 306 switch(buf[0]) { 307 case '\n': 308 if(curpos.y+h >= window.max.y) 309 scroll(); 310 curpos.y += h; 311 screenputc("\r"); 312 break; 313 case '\r': 314 xp = xbuf; 315 curpos.x = window.min.x; 316 break; 317 case '\t': 318 p = memsubfontwidth(memdefont, " "); 319 w = p.x; 320 *xp++ = curpos.x; 321 pos = (curpos.x-window.min.x)/w; 322 pos = 8-(pos%8); 323 curpos.x += pos*w; 324 break; 325 case '\b': 326 if(xp <= xbuf) 327 break; 328 xp--; 329 r = Rpt(Pt(*xp, curpos.y), Pt(curpos.x, curpos.y + h)); 330 memdraw(&gscreen, r, back, back->r.min, memones, back->r.min); 331 curpos.x = *xp; 332 break; 333 default: 334 p = memsubfontwidth(memdefont, buf); 335 w = p.x; 336 337 if(curpos.x >= window.max.x-w) 338 screenputc("\n"); 339 340 *xp++ = curpos.x; 341 memimagestring(&gscreen, curpos, &conscol, memdefont, buf); 342 curpos.x += w; 343 } 344 } 345 346 void 347 screenputs(char *s, int n) 348 { 349 int i; 350 Rune r; 351 char buf[4]; 352 extern int cold; 353 354 if(!cold) 355 return; 356 357 if(islo() == 0) { 358 /* don't deadlock trying to print in interrupt */ 359 if(!canlock(&screenlock)) 360 return; 361 } else 362 lock(&screenlock); 363 364 while(n > 0) { 365 i = chartorune(&r, s); 366 if(i == 0){ 367 s++; 368 --n; 369 continue; 370 } 371 memmove(buf, s, i); 372 buf[i] = 0; 373 n -= i; 374 s += i; 375 screenputc(buf); 376 } 377 378 unlock(&screenlock); 379 } 380 381 382 void 383 cursorenable(void) 384 { 385 if(vctlr->enable == nil) 386 return; 387 388 vctlr->enable(); 389 390 if(!vctlr->isloaded()) 391 vctlr->load(&arrow); 392 } 393 394 void 395 cursordisable(void) 396 { 397 if(vctlr->disable == nil) 398 return; 399 400 vctlr->disable(); 401 } 402 403 static Rectangle cursoroffrect; 404 static int cursorisoff; 405 static Point hot; 406 407 void 408 cursorupdate0(void) 409 { 410 int inrect, x, y; 411 412 x = mouse.x - hot.x; 413 y = mouse.y - hot.y; 414 inrect = (x >= cursoroffrect.min.x && x < cursoroffrect.max.x 415 && y >= cursoroffrect.min.y && y < cursoroffrect.max.y); 416 if (cursorisoff == inrect) 417 return; 418 cursorisoff = inrect; 419 if (inrect) 420 cursordisable(); 421 else 422 cursorenable(); 423 } 424 425 void 426 cursorupdate(Rectangle r) 427 { 428 lock(&screenlock); 429 r.min.x -= 16; 430 r.min.y -= 16; 431 cursoroffrect = r; 432 if (swcursor) 433 cursorupdate0(); 434 unlock(&screenlock); 435 } 436 437 void 438 drawcursor(Drawcursor* c) 439 { 440 Cursor curs; 441 int j, i, h, bpl; 442 uchar *bc, *bs, *cclr, *cset; 443 444 if(vctlr->load == nil) 445 return; 446 447 /* Set the default system cursor */ 448 if(c->data == nil) { 449 lock(&screenlock); 450 vctlr->load(&arrow); 451 unlock(&screenlock); 452 return; 453 } 454 455 hot.x = c->hotx; 456 hot.y = c->hoty; 457 curs.offset = hot; 458 bpl = bytesperline(Rect(c->minx, c->miny, c->maxx, c->maxy), 0); 459 460 h = (c->maxy-c->miny)/2; 461 if(h > 16) 462 h = 16; 463 464 bc = c->data; 465 bs = c->data + h*bpl; 466 467 cclr = curs.clr; 468 cset = curs.set; 469 for(i = 0; i < h; i++) { 470 for(j = 0; j < 2; j++) { 471 cclr[j] = bc[j]; 472 cset[j] = bs[j]; 473 } 474 bc += bpl; 475 bs += bpl; 476 cclr += 2; 477 cset += 2; 478 } 479 lock(&screenlock); 480 vctlr->load(&curs); 481 unlock(&screenlock); 482 } 483 484