1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "io.h" 7 #include "../port/error.h" 8 9 #include <draw.h> 10 #include <memdraw.h> 11 #include <cursor.h> 12 13 #include "screen.h" 14 15 enum { 16 Backgnd = 0xFF, /* white */ 17 Foregnd = 0x00, /* black */ 18 }; 19 20 Cursor arrow = { 21 { -1, -1 }, 22 { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C, 23 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, 24 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04, 25 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40, 26 }, 27 { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0, 28 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8, 29 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8, 30 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00, 31 }, 32 }; 33 34 static Memdata xgdata; 35 static Memimage xgscreen = 36 { 37 {0, 0, 0, 0}, /* r */ 38 {0, 0, 0, 0}, /* clipr */ 39 8, /* depth */ 40 1, /* nchan */ 41 CMAP8, /* chan */ 42 nil, /* cmap */ 43 &xgdata, /* data */ 44 0, /* zero */ 45 0, /* width */ 46 nil, /* layer */ 47 0, /* flags */ 48 }; 49 50 int novgascreen; /* optionally set by configuration file */ 51 static int lcdpdpar; /* value to load into io->pdpar */ 52 53 Memimage *gscreen; 54 Memimage *conscol; 55 Memimage *back; 56 57 static Memsubfont *memdefont; 58 static Lock palettelock; /* access to DAC registers */ 59 static Lock screenlock; 60 static int h; 61 static Point curpos; 62 static Rectangle window; 63 64 typedef struct SWcursor SWcursor; 65 static SWcursor *swc = nil; 66 SWcursor* swcurs_create(ulong *, int, int, Rectangle, int); 67 void swcurs_destroy(SWcursor*); 68 void swcurs_enable(SWcursor*); 69 void swcurs_disable(SWcursor*); 70 void swcurs_hide(SWcursor*); 71 void swcurs_unhide(SWcursor*); 72 void swcurs_load(SWcursor*, Cursor*); 73 74 static void screenputc(char*); 75 static void scroll(void); 76 static void setscreen(Mode*); 77 static void cursorlock(Rectangle); 78 static void cursorunlock(void); 79 static void lcdinit(Mode*); 80 static void lcdsetrgb(int, ulong, ulong, ulong); 81 82 /* 83 * Called by main(). 84 */ 85 void 86 screeninit(void) 87 { 88 Mode m; 89 90 novgascreen=1; return; 91 92 /* default size and parameters */ 93 memset(&m.lcd, 0, sizeof(m.lcd)); 94 m.x = 640; 95 m.y = 480; 96 m.d = 3; 97 if(novgascreen == 0 && archlcdmode(&m) >= 0){ 98 memdefont = getmemdefont(); 99 setscreen(&m); 100 } 101 } 102 103 /* 104 * On 8 bit displays, load the default color map 105 */ 106 void 107 graphicscmap(int invert) 108 { 109 int num, den, i, j; 110 int r, g, b, cr, cg, cb, v; 111 112 for(r=0,i=0;r!=4;r++) for(v=0;v!=4;v++,i+=16){ 113 for(g=0,j=v-r;g!=4;g++) for(b=0;b!=4;b++,j++){ 114 den=r; 115 if(g>den) den=g; 116 if(b>den) den=b; 117 if(den==0) /* divide check -- pick grey shades */ 118 cr=cg=cb=v*17; 119 else{ 120 num=17*(4*den+v); 121 cr=r*num/den; 122 cg=g*num/den; 123 cb=b*num/den; 124 } 125 if(invert) 126 setcolor(255-i-(j&15), 127 cr*0x01010101, cg*0x01010101, cb*0x01010101); 128 else 129 setcolor(i+(j&15), 130 cr*0x01010101, cg*0x01010101, cb*0x01010101); 131 } 132 } 133 } 134 135 /* 136 * reconfigure screen shape 137 */ 138 static void 139 setscreen(Mode *mode) 140 { 141 int h; 142 143 if(swc) 144 swcurs_destroy(swc); 145 146 gscreen = &xgscreen; 147 xgdata.ref = 1; 148 lcdinit(mode); 149 xgdata.bdata = (uchar*)mode->aperture; 150 if(xgdata.bdata == nil) 151 panic("setscreen: vga soft memory"); 152 153 gscreen->r = Rect(0, 0, mode->x, mode->y); 154 gscreen->clipr = gscreen->r; 155 gscreen->depth = 1<<mode->d; 156 gscreen->width = wordsperline(gscreen->r, gscreen->depth); 157 memimageinit(); 158 memdefont = getmemdefont(); 159 160 memsetchan(gscreen, CMAP8); 161 back = memwhite; 162 conscol = memblack; 163 memimagedraw(gscreen, gscreen->r, memwhite, ZP, memopaque, ZP, SoverD); 164 graphicscmap(0); 165 166 /* get size for a system window */ 167 h = memdefont->height; 168 window = insetrect(gscreen->r, 4); 169 window.max.y = window.min.y+(Dy(window)/h)*h; 170 curpos = window.min; 171 // screenclear(); 172 173 graphicscmap(0); 174 175 // swc = swcurs_create(gscreendata.data, gscreen.width, gscreen.ldepth, gscreen.r, 1); 176 177 drawcursor(nil); 178 } 179 180 enum { 181 ScreenCached = 1 /* non-zero if screen region not write-through */ 182 }; 183 184 void 185 flushmemscreen(Rectangle r) 186 { 187 if(rectclip(&r, gscreen->r) == 0) 188 return; 189 if(r.min.x >= r.max.x || r.min.y >= r.max.y) 190 return; 191 if(ScreenCached) 192 dcflush((ulong*)gscreen->data->bdata + gscreen->width*r.min.y, gscreen->width*Dy(r)); 193 } 194 195 /* 196 * export screen to interpreter 197 */ 198 uchar* 199 attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen) 200 { 201 *r = gscreen->r; 202 *d = gscreen->depth; 203 *chan = gscreen->chan; 204 *width = gscreen->width; 205 *softscreen = ScreenCached; 206 207 return (uchar*)gscreen->data->bdata; 208 } 209 210 void 211 detachscreen(void) 212 { 213 } 214 215 /* 216 * write a string to the screen 217 */ 218 void 219 screenputs(char *s, int n) 220 { 221 int i; 222 Rune r; 223 char buf[4]; 224 225 if(novgascreen || xgdata.bdata == nil || memdefont == nil) 226 return; 227 if(islo() == 0) { 228 /* don't deadlock trying to print in interrupt */ 229 if(!canlock(&screenlock)) 230 return; 231 } else 232 lock(&screenlock); 233 234 while(n > 0) { 235 i = chartorune(&r, s); 236 if(i == 0){ 237 s++; 238 --n; 239 continue; 240 } 241 memmove(buf, s, i); 242 buf[i] = 0; 243 n -= i; 244 s += i; 245 screenputc(buf); 246 } 247 /* Only OK for now */ 248 flushmemscreen(gscreen->r); 249 250 unlock(&screenlock); 251 } 252 253 static void 254 scroll(void) 255 { 256 int o; 257 Point p; 258 Rectangle r; 259 260 o = 4*memdefont->height; 261 r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); 262 p = Pt(window.min.x, window.min.y+o); 263 memimagedraw(gscreen, r, gscreen, p, nil, p, SoverD); 264 flushmemscreen(r); 265 r = Rpt(Pt(window.min.x, window.max.y-o), window.max); 266 memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD); 267 flushmemscreen(r); 268 269 curpos.y -= o; 270 } 271 272 static void 273 clearline(void) 274 { 275 Rectangle r; 276 int yloc = curpos.y; 277 278 r = Rpt(Pt(window.min.x, window.min.y + yloc), 279 Pt(window.max.x, window.min.y+yloc+memdefont->height)); 280 memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD); 281 } 282 283 static void 284 screenputc(char *buf) 285 { 286 Point p; 287 int h, w, pos; 288 Rectangle r; 289 static int *xp; 290 static int xbuf[256]; 291 292 h = memdefont->height; 293 if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) 294 xp = xbuf; 295 296 switch(buf[0]) { 297 case '\n': 298 if(curpos.y+h >= window.max.y) 299 scroll(); 300 curpos.y += h; 301 /* fall through */ 302 case '\r': 303 xp = xbuf; 304 curpos.x = window.min.x; 305 break; 306 case '\t': 307 if(curpos.x == window.min.x) 308 clearline(); 309 p = memsubfontwidth(memdefont, " "); 310 w = p.x; 311 *xp++ = curpos.x; 312 pos = (curpos.x-window.min.x)/w; 313 pos = 8-(pos%8); 314 r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y+h); 315 memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD); 316 flushmemscreen(r); 317 curpos.x += pos*w; 318 break; 319 case '\b': 320 if(xp <= xbuf) 321 break; 322 xp--; 323 r = Rpt(Pt(*xp, curpos.y), Pt(curpos.x, curpos.y + h)); 324 memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD); 325 flushmemscreen(r); 326 curpos.x = *xp; 327 break; 328 case '\0': 329 break; 330 default: 331 p = memsubfontwidth(memdefont, buf); 332 w = p.x; 333 334 if(curpos.x >= window.max.x-w) 335 screenputc("\n"); 336 337 if(curpos.x == window.min.x) 338 clearline(); 339 if(xp < xbuf+nelem(xbuf)) 340 *xp++ = curpos.x; 341 r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h); 342 memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD); 343 memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf); 344 flushmemscreen(r); 345 curpos.x += w; 346 } 347 } 348 349 int 350 setcolor(ulong p, ulong r, ulong g, ulong b) 351 { 352 ulong x; 353 354 if(gscreen->depth >= 8) 355 x = 0xFF; 356 else 357 x = 0xF; 358 p &= x; 359 p ^= x; 360 lock(&palettelock); 361 lcdsetrgb(p, r, g, b); 362 unlock(&palettelock); 363 return ~0; 364 } 365 366 void 367 getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) 368 { 369 /* TO DO */ 370 *pr = *pg = *pb = 0; 371 } 372 373 /* 374 * See section 5.2.1 (page 5-6) of the MPC823 manual 375 */ 376 static uchar lcdclock[17] = { /* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */ 377 0, 0, (1<<2), 1, 378 (2<<2), 2, (1<<2)|1, 3, 379 (3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1, 380 (2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2), 381 (4<<2) 382 }; 383 384 enum { 385 /* lccr */ 386 Enable = 1<<0, 387 388 /* lchcr */ 389 BigEndian = 1<<24, 390 AT7 = 7<<21, /* access type */ 391 392 /* sdcr */ 393 LAM = 1<<6, /* ``LCD aggressive mode'' */ 394 }; 395 396 /* 397 * initialise MPC8xx LCD controller incorporating board or display-specific values in Mode.lcd 398 */ 399 static void 400 lcdinit(Mode *mode) 401 { 402 IMM *io; 403 int i, d; 404 long hz; 405 406 io = m->iomem; 407 mode->aperture = xspanalloc(mode->x*mode->y, 16, 0); 408 mode->apsize = mode->x*mode->y; 409 410 io->sdcr = 1; /* MPC823 errata: turn off LAM before disabling controller */ 411 eieio(); 412 io->lcfaa = PADDR(mode->aperture); 413 io->lccr = (((mode->x*mode->y*(1<<mode->d)+127)/128) << 17) | (mode->d << 5) | mode->lcd.flags; 414 switch(mode->d){ 415 default: 416 case 0: 417 /* monochrome/greyscale identity map */ 418 for(i=0; i<16; i++) 419 io->lcdmap[i] = i; 420 break; 421 case 2: 422 /* 4-bit grey scale map */ 423 for(i=0; i<16; i++) 424 io->lcdmap[0] = (i<<8)|(i<<4)|i; 425 break; 426 case 3: 427 /* 8-bit linear map */ 428 for(i=0; i<256; i++) 429 io->lcdmap[i] = (i<<8)|(i<<4)|i; 430 break; 431 } 432 433 io->lcvcr = (mode->y << 11) | (mode->lcd.vpw<<28) | (mode->lcd.ac<<21) | mode->lcd.wbf; 434 io->lchcr = (mode->x<<10) | BigEndian | mode->lcd.wbl; 435 436 hz = m->cpuhz; 437 d = hz/mode->lcd.freq; 438 if(hz/d > mode->lcd.freq) 439 d++; 440 if(d >= 16) 441 d = 16; 442 443 /* 444 * enable LCD outputs 445 */ 446 io->pddat = 0; 447 lcdpdpar = 0x1fff & ~mode->lcd.notpdpar; 448 io->pdpar = lcdpdpar; 449 io->pddir = 0x1fff; 450 io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17); 451 io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17); 452 io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17)); 453 454 /* 455 * with the data cache off, early revisions of the 823 did not require 456 * the `aggressive' DMA priority to avoid flicker, but flicker is obvious 457 * on the 823A when the cache is on, so LAM is now set 458 */ 459 io->sdcr = (io->sdcr & ~0xF) | LAM; /* LAM=1, LAID=0, RAID=0 */ 460 461 // gscreen.width = gscreen.width; /* access external memory before enabling (mpc823 errata) */ 462 eieio(); 463 io->sccrk = KEEP_ALIVE_KEY; 464 eieio(); 465 io->sccr = (io->sccr & ~0x1F) | lcdclock[d]; 466 eieio(); 467 io->sccrk= ~KEEP_ALIVE_KEY; 468 io->lcsr = 7; /* clear status */ 469 eieio(); 470 io->lccr |= Enable; 471 archbacklight(1); 472 } 473 474 static void 475 lcdsetrgb(int p, ulong r, ulong g, ulong b) 476 { 477 r >>= 28; 478 g >>= 28; 479 b >>= 28; 480 m->iomem->lcdmap[p&0xFF] = (r<<8) | (g<<4) | b; 481 } 482 483 void 484 blankscreen(int blank) 485 { 486 USED(blank); /* TO DO */ 487 } 488 489 /* 490 * enable/disable LCD panel (eg, when using video subsystem) 491 */ 492 void 493 lcdpanel(int on) 494 { 495 IMM *io; 496 497 if(on){ 498 archbacklight(1); 499 io = ioplock(); 500 io->pddat = 0; 501 io->pdpar = lcdpdpar; 502 io->pddir = 0x1fff; 503 io->lccr |= Enable; 504 iopunlock(); 505 }else{ 506 io = ioplock(); 507 io->sdcr = 1; /* MPC823 errata: turn off LAM before disabling controller */ 508 eieio(); 509 io->pddir = 0; 510 eieio(); 511 io->lccr &= ~Enable; 512 iopunlock(); 513 archbacklight(0); 514 } 515 } 516 517 /* 518 * Software cursor code. Interim version (for baseline). 519 * we may want to replace code here by memdraw primitives. 520 */ 521 522 enum { 523 CUR_ENA = 0x01, /* cursor is enabled */ 524 CUR_DRW = 0x02, /* cursor is currently drawn */ 525 CUR_SWP = 0x10, /* bit swap */ 526 CURSWID = 16, 527 CURSHGT = 16, 528 }; 529 530 typedef struct SWcursor { 531 ulong *fb; /* screen frame buffer */ 532 Rectangle r; 533 int d; /* ldepth of screen */ 534 int width; /* width of screen in ulongs */ 535 int x; 536 int y; 537 int hotx; 538 int hoty; 539 uchar cbwid; /* cursor byte width */ 540 uchar f; /* flags */ 541 uchar cwid; 542 uchar chgt; 543 int hidecount; 544 uchar data[CURSWID*CURSHGT]; 545 uchar mask[CURSWID*CURSHGT]; 546 uchar save[CURSWID*CURSHGT]; 547 } SWcursor; 548 549 static Rectangle cursoroffrect; 550 static int cursorisoff; 551 552 static void swcursorflush(int, int); 553 static void swcurs_draw_or_undraw(SWcursor *); 554 555 static void 556 cursorupdate0(void) 557 { 558 int inrect, x, y; 559 Point m; 560 561 m = mousexy(); 562 x = m.x - swc->hotx; 563 y = m.y - swc->hoty; 564 inrect = (x >= cursoroffrect.min.x && x < cursoroffrect.max.x 565 && y >= cursoroffrect.min.y && y < cursoroffrect.max.y); 566 if (cursorisoff == inrect) 567 return; 568 cursorisoff = inrect; 569 if (inrect) 570 swcurs_hide(swc); 571 else { 572 swc->hidecount = 0; 573 swcurs_draw_or_undraw(swc); 574 } 575 swcursorflush(m.x, m.y); 576 } 577 578 void 579 cursorupdate(Rectangle r) 580 { 581 lock(&screenlock); 582 r.min.x -= 16; 583 r.min.y -= 16; 584 cursoroffrect = r; 585 if (swc) 586 cursorupdate0(); 587 unlock(&screenlock); 588 } 589 590 void 591 cursorenable(void) 592 { 593 Point m; 594 595 lock(&screenlock); 596 if(swc) { 597 swcurs_enable(swc); 598 m = mousexy(); 599 swcursorflush(m.x, m.y); 600 } 601 unlock(&screenlock); 602 } 603 604 void 605 cursordisable(void) 606 { 607 Point m; 608 609 lock(&screenlock); 610 if(swc) { 611 swcurs_disable(swc); 612 m = mousexy(); 613 swcursorflush(m.x, m.y); 614 } 615 unlock(&screenlock); 616 } 617 618 void 619 drawcursor(Drawcursor* c) 620 { 621 Point p; 622 Cursor curs, *cp; 623 int j, i, h, bpl; 624 uchar *bc, *bs, *cclr, *cset; 625 626 if(!swc) 627 return; 628 629 /* Set the default system cursor */ 630 if(!c || c->data == nil) 631 cp = &arrow /*&crosshair_black*/; 632 else { 633 cp = &curs; 634 p.x = c->hotx; 635 p.y = c->hoty; 636 cp->offset = p; 637 bpl = bytesperline(Rect(c->minx, c->miny, c->maxx, c->maxy), 1); 638 639 h = (c->maxy-c->miny)/2; 640 if(h > 16) 641 h = 16; 642 643 bc = c->data; 644 bs = c->data + h*bpl; 645 646 cclr = cp->clr; 647 cset = cp->set; 648 for(i = 0; i < h; i++) { 649 for(j = 0; j < 2; j++) { 650 cclr[j] = bc[j]; 651 cset[j] = bs[j]; 652 } 653 bc += bpl; 654 bs += bpl; 655 cclr += 2; 656 cset += 2; 657 } 658 } 659 660 if(swc) { 661 swcurs_load(swc, cp); 662 p = mousexy(); 663 swcursorflush(p.x, p.y); 664 } 665 } 666 667 SWcursor* 668 swcurs_create(ulong *fb, int width, int ldepth, Rectangle r, int bitswap) 669 { 670 SWcursor *swc = (SWcursor*)malloc(sizeof(SWcursor)); 671 swc->fb = fb; 672 swc->r = r; 673 swc->d = ldepth; 674 swc->width = width; 675 swc->f = bitswap ? CUR_SWP : 0; 676 swc->x = swc->y = 0; 677 swc->hotx = swc->hoty = 0; 678 swc->hidecount = 0; 679 return swc; 680 } 681 682 void 683 swcurs_destroy(SWcursor *swc) 684 { 685 swcurs_disable(swc); 686 free(swc); 687 } 688 689 static void 690 swcursorflush(int x, int y) 691 { 692 Rectangle r; 693 694 /* XXX a little too paranoid here */ 695 r.min.x = x-16; 696 r.min.y = y-16; 697 r.max.x = x+17; 698 r.max.y = y+17; 699 flushmemscreen(r); 700 } 701 702 static void 703 swcurs_draw_or_undraw(SWcursor *swc) 704 { 705 uchar *p; 706 uchar *cs; 707 int w, vw; 708 int x1 = swc->r.min.x; 709 int y1 = swc->r.min.y; 710 int x2 = swc->r.max.x; 711 int y2 = swc->r.max.y; 712 int xp = swc->x - swc->hotx; 713 int yp = swc->y - swc->hoty; 714 int ofs; 715 716 if(((swc->f & CUR_ENA) && (swc->hidecount <= 0)) 717 == ((swc->f & CUR_DRW) != 0)) 718 return; 719 w = swc->cbwid*BI2BY/(1 << swc->d); 720 x1 = xp < x1 ? x1 : xp; 721 y1 = yp < y1 ? y1 : yp; 722 x2 = xp+w >= x2 ? x2 : xp+w; 723 y2 = yp+swc->chgt >= y2 ? y2 : yp+swc->chgt; 724 if(x2 <= x1 || y2 <= y1) 725 return; 726 p = (uchar*)(swc->fb + swc->width*y1) 727 + x1*(1 << swc->d)/BI2BY; 728 y2 -= y1; 729 x2 = (x2-x1)*(1 << swc->d)/BI2BY; 730 vw = swc->width*BY2WD - x2; 731 w = swc->cbwid - x2; 732 ofs = swc->cbwid*(y1-yp)+(x1-xp); 733 cs = swc->save + ofs; 734 if((swc->f ^= CUR_DRW) & CUR_DRW) { 735 uchar *cm = swc->mask + ofs; 736 uchar *cd = swc->data + ofs; 737 while(y2--) { 738 x1 = x2; 739 while(x1--) { 740 *p = ((*cs++ = *p) & *cm++) ^ *cd++; 741 p++; 742 } 743 cs += w; 744 cm += w; 745 cd += w; 746 p += vw; 747 } 748 } else { 749 while(y2--) { 750 x1 = x2; 751 while(x1--) 752 *p++ = *cs++; 753 cs += w; 754 p += vw; 755 } 756 } 757 } 758 759 void 760 swcurs_hide(SWcursor *swc) 761 { 762 ++swc->hidecount; 763 swcurs_draw_or_undraw(swc); 764 } 765 766 void 767 swcurs_unhide(SWcursor *swc) 768 { 769 if (--swc->hidecount < 0) 770 swc->hidecount = 0; 771 swcurs_draw_or_undraw(swc); 772 } 773 774 void 775 swcurs_enable(SWcursor *swc) 776 { 777 swc->f |= CUR_ENA; 778 swcurs_draw_or_undraw(swc); 779 } 780 781 void 782 swcurs_disable(SWcursor *swc) 783 { 784 swc->f &= ~CUR_ENA; 785 swcurs_draw_or_undraw(swc); 786 } 787 788 void 789 swcurs_load(SWcursor *swc, Cursor *c) 790 { 791 int i, k; 792 uchar *bc, *bs, *cd, *cm; 793 static uchar bdv[4] = {0,Backgnd,Foregnd,0xff}; 794 static uchar bmv[4] = {0xff,0,0,0xff}; 795 int bits = 1<<swc->d; 796 uchar mask = (1<<bits)-1; 797 int bswp = (swc->f&CUR_SWP) ? 8-bits : 0; 798 799 bc = c->clr; 800 bs = c->set; 801 802 swcurs_hide(swc); 803 cd = swc->data; 804 cm = swc->mask; 805 swc->hotx = c->offset.x; 806 swc->hoty = c->offset.y; 807 swc->chgt = CURSHGT; 808 swc->cwid = CURSWID; 809 swc->cbwid = CURSWID*(1<<swc->d)/BI2BY; 810 for(i = 0; i < CURSWID/BI2BY*CURSHGT; i++) { 811 uchar bcb = *bc++; 812 uchar bsb = *bs++; 813 for(k=0; k<BI2BY;) { 814 uchar cdv = 0; 815 uchar cmv = 0; 816 int z; 817 for(z=0; z<BI2BY; z += bits) { 818 int n = ((bsb&(0x80))|((bcb&(0x80))<<1))>>7; 819 int s = z^bswp; 820 cdv |= (bdv[n]&mask) << s; 821 cmv |= (bmv[n]&mask) << s; 822 bcb <<= 1; 823 bsb <<= 1; 824 k++; 825 } 826 *cd++ = cdv; 827 *cm++ = cmv; 828 } 829 } 830 swcurs_unhide(swc); 831 } 832 833