ite_cc.c revision 1.6 1 #include "ite.h"
2 #if ! defined (NITE)
3 #define NITE 1
4 #endif
5 #if NITE > 0
6
7 #include "param.h"
8 #include "conf.h"
9 #include "proc.h"
10 #include "ioctl.h"
11 #include "tty.h"
12 #include "systm.h"
13
14 #include "ite.h"
15 #include "itevar.h"
16 #include "iteioctl.h"
17 #include "machine/cpu.h"
18
19 #include "../amiga/cc_types.h"
20 #include "../amiga/cc_chipmem.h"
21
22 #include "grf/grf_types.h"
23 #include "grf/grf_view.h"
24 #include "grf/grf_bitmap.h"
25 #include "viewioctl.h"
26 #include "viewvar.h"
27 #include "termios.h"
28
29 extern unsigned char kernel_font_width, kernel_font_height, kernel_font_baseline;
30 extern short kernel_font_boldsmear;
31 extern unsigned char kernel_font_lo, kernel_font_hi;
32 extern unsigned char kernel_font[], kernel_cursor[];
33
34 /*
35 * This is what ip->priv points to;
36 * it contains local variables for custom-chip ites.
37 */
38 typedef struct ite_priv {
39 view_t *view; /* the view for this ite. */
40 u_char **row_ptr; /* array of pointers into the bitmap */
41 u_long row_bytes;
42 u_long cursor_opt;
43
44 /* these are precalc'ed for the putc routine so it can be faster. */
45 u_int *column_offset; /* array of offsets for columns */
46 u_int row_offset; /* the row offset */
47 u_word width; /* the bitmap width */
48 u_word underline; /* where the underline goes */
49 u_word ft_x; /* the font width */
50 u_word ft_y; /* the font height */
51 u_char *font_cell[256]; /* the font pointer */
52 } ipriv_t;
53
54 extern struct itesw itesw[];
55
56 /* (M<=8)-by-N routines */
57 static void view_le32n_cursor(struct ite_softc *ip, int flag);
58 static void view_le8n_putc(struct ite_softc *ip, int c, int dy, int dx, int mode);
59 static void view_le8n_clear(struct ite_softc *ip, int sy, int sx, int h, int w);
60 static void view_le8n_scroll(struct ite_softc *ip, int sy, int sx, int count, int dir);
61 void scroll_bitmap (bmap_t *bm, u_word x, u_word y, u_word width, u_word height, word dx, word dy, u_byte mask);
62
63
64 /* globals */
65
66 int ite_default_x;
67 int ite_default_y;
68 int ite_default_width = 640;
69
70 #if defined (GRF_NTSC)
71 int ite_default_height = 400;
72 int ite_default_depth = 2;
73 #elif defined (GRF_PAL)
74 int ite_default_height = 512;
75 int ite_default_depth = 2;
76 #else
77 int ite_default_height = 400;
78 int ite_default_depth = 2;
79 #endif
80
81 /* audio bell stuff */
82 static char *bell_data;
83 static struct ite_bell_values bell_vals = { 64, 200, 10 };
84
85 cc_unblank ()
86 {
87 }
88
89 init_bell ()
90 {
91 short i;
92 static char sample[20] = {
93 0,39,75,103,121,127,121,103,75,39,0,
94 -39,-75,-103,-121,-127,-121,-103,-75,-39 };
95
96 if (!bell_data) {
97 bell_data = alloc_chipmem(20);
98 if (!bell_data)
99 return (-1);
100
101 for (i=0; i<20; i++)
102 bell_data[i] = sample[i];
103 }
104 return (0);
105 }
106
107 cc_bell ()
108 {
109 if (bell_data) {
110 play_sample (10, PREP_DMA_MEM(bell_data),
111 bell_vals.period, bell_vals.volume, 0x3, bell_vals.time);
112 }
113 }
114
115 extern struct ite_softc ite_softc[];
116 #define IPUNIT(ip) (((u_long)ip-(u_long)ite_softc)/sizeof(struct ite_softc))
117
118 int
119 ite_new_size (struct ite_softc *ip, struct ite_window_size *vs)
120 {
121 extern struct view_softc views[];
122 ipriv_t *cci = ip->priv;
123 u_long fbp, i;
124 int error;
125
126 error = viewioctl (IPUNIT (ip), VIEW_SETSIZE, (struct view_size *)vs, 0, -1);
127 cci->view = views[IPUNIT(ip)].view;
128
129 ip->rows = (cci->view->display.height) / ip->ftheight;
130 ip->cols = (cci->view->display.width-1) / ip->ftwidth; /* -1 for bold. */
131
132 if (cci->row_ptr)
133 free_chipmem (cci->row_ptr);
134 if (cci->column_offset)
135 free_chipmem (cci->column_offset);
136
137 cci->row_ptr = alloc_chipmem (sizeof (u_byte *)*ip->rows);
138 cci->column_offset = alloc_chipmem (sizeof (u_int)*ip->cols);
139
140 if (!cci->row_ptr || !cci->column_offset) {
141 panic ("no memory for console device.");
142 }
143
144 cci->width = cci->view->bitmap->bytes_per_row << 3;
145 cci->underline = ip->ftbaseline + 1;
146 cci->row_offset = (cci->view->bitmap->bytes_per_row + cci->view->bitmap->row_mod);
147 cci->ft_x = ip->ftwidth;
148 cci->ft_y = ip->ftheight;
149
150 cci->row_bytes = cci->row_offset * ip->ftheight;
151
152 /* initialize the row pointers */
153 cci->row_ptr[0] = VDISPLAY_LINE (cci->view, 0, 0);
154 for (i = 1; i < ip->rows; i++)
155 cci->row_ptr[i] = cci->row_ptr[i-1] + cci->row_bytes;
156
157 /* initialize the column offsets */
158 cci->column_offset[0] = 0;
159 for (i = 1; i < ip->cols; i++)
160 cci->column_offset[i] = cci->column_offset[i-1] + cci->ft_x;
161
162 /* initialize the font cell pointers */
163 cci->font_cell[ip->font_lo] = ip->font;
164 for (i=ip->font_lo+1; i<=ip->font_hi; i++)
165 cci->font_cell[i] = cci->font_cell[i-1] + ip->ftheight;
166
167 return (error);
168 }
169
170
171 ite_view_init(ip)
172 register struct ite_softc *ip;
173 {
174 struct itesw *sp = itesw;
175 ipriv_t *cci = ip->priv;
176 struct ite_window_size vs;
177
178 init_bell ();
179
180 if (!cci) {
181 ip->font = kernel_font;
182 ip->font_lo = kernel_font_lo;
183 ip->font_hi = kernel_font_hi;
184 ip->ftwidth = kernel_font_width;
185 ip->ftheight = kernel_font_height;
186 ip->ftbaseline = kernel_font_baseline;
187 ip->ftboldsmear = kernel_font_boldsmear;
188
189 /* Find the correct set of rendering routines for this font. */
190 if (ip->ftwidth <= 8) {
191 sp->ite_cursor = (void*)view_le32n_cursor;
192 sp->ite_putc = (void*)view_le8n_putc;
193 sp->ite_clear = (void*)view_le8n_clear;
194 sp->ite_scroll = (void*)view_le8n_scroll;
195 } else {
196 panic("kernel font size not supported");
197 }
198
199 cci = alloc_chipmem (sizeof (*cci));
200 if (!cci) {
201 panic ("no memory for console device.");
202 }
203
204 ip->priv = cci;
205 cci->cursor_opt = 0;
206 cci->view = NULL;
207 cci->row_ptr = NULL;
208 cci->column_offset = NULL;
209
210 #if 0
211 /* currently the view is permanently open due to grf driver */
212 if (viewopen (IPUNIT(ip), 0)) {
213 panic ("cannot get ahold of our view");
214 }
215 #endif
216 vs.x = ite_default_x;
217 vs.y = ite_default_y;
218 vs.width = ite_default_width;
219 vs.height = ite_default_height;
220 vs.depth = ite_default_depth;
221
222 ite_new_size (ip, &vs);
223 XXX_grf_cc_on (IPUNIT (ip));
224 /* viewioctl (IPUNIT(ip), VIEW_DISPLAY, NULL, 0, -1); */
225 }
226 }
227
228 int
229 ite_grf_ioctl (ip, cmd, addr, flag)
230 struct ite_softc *ip;
231 caddr_t addr;
232 {
233 int error = 0;
234 struct ite_window_size *is;
235 struct ite_bell_values *ib;
236 ipriv_t *cci = ip->priv;
237
238 switch (cmd) {
239 case ITE_GET_WINDOW_SIZE:
240 is = (struct ite_window_size *)addr;
241 is->x = cci->view->display.x;
242 is->y = cci->view->display.y;
243 is->width = cci->view->display.width;
244 is->height = cci->view->display.height;
245 is->depth = cci->view->bitmap->depth;
246 break;
247
248 case ITE_SET_WINDOW_SIZE:
249 is = (struct ite_window_size *)addr;
250
251 if (ite_new_size (ip, is)) {
252 error = ENOMEM;
253 } else {
254 struct winsize ws;
255 ws.ws_row = ip->rows;
256 ws.ws_col = ip->cols;
257 ws.ws_xpixel = cci->view->display.width;
258 ws.ws_ypixel = cci->view->display.height;
259 ite_reset (ip);
260 /* XXX tell tty about the change *and* the process group should */
261 /* XXX be signalled---this is messy, but works nice :^) */
262 iteioctl (0, TIOCSWINSZ, &ws, 0);
263 }
264 break;
265
266 case ITE_DISPLAY_WINDOW:
267 XXX_grf_cc_on (IPUNIT (ip));
268 /* viewioctl (IPUNIT(ip), VIEW_DISPLAY, NULL, 0, -1); */
269 break;
270
271 case ITE_REMOVE_WINDOW:
272 XXX_grf_cc_off (IPUNIT (ip));
273 /* viewioctl (IPUNIT(ip), VIEW_REMOVE, NULL, 0, -1); */
274 break;
275
276 case ITE_GET_BELL_VALUES:
277 ib = (struct ite_bell_values *)addr;
278 bcopy (&bell_vals, ib, sizeof (struct ite_bell_values));
279 break;
280
281 case ITE_SET_BELL_VALUES:
282 ib = (struct ite_bell_values *)addr;
283 bcopy (ib, &bell_vals, sizeof (struct ite_bell_values));
284 break;
285 case VIEW_USECOLORMAP:
286 case VIEW_GETCOLORMAP:
287 /* XXX needs to be fixed when multiple console implemented. */
288 /* XXX watchout for that -1 its not really the kernel talking. */
289 /* XXX these two commands don't use the proc pointer though. */
290 error = viewioctl (0, cmd, addr, flag, -1);
291 break;
292 default:
293 error = -1;
294 break;
295 }
296 return (error);
297 }
298
299 ite_view_deinit(ip)
300 struct ite_softc *ip;
301 {
302 ip->flags &= ~ITE_INITED;
303 /* FIX: free our stuff. */
304 if (ip->priv) {
305 ipriv_t *cci = ip->priv;
306
307 #if 0
308 /* view stays open permanently */
309 if (cci->view) {
310 viewclose (IPUNIT(ip));
311 }
312
313 /* well at least turn it off. */
314 XXX_grf_cc_off (IPUNIT (ip));
315 /* viewioctl (IPUNIT(ip), VIEW_REMOVE, NULL, 0, -1); */
316 #endif
317
318 if (cci->row_ptr)
319 free_chipmem (cci->row_ptr);
320 if (cci->column_offset)
321 free_chipmem (cci->column_offset);
322
323 free_chipmem (cci);
324 ip->priv = NULL;
325 }
326 }
327
328 /*** (M<8)-by-N routines ***/
329
330 static void
331 view_le32n_cursor(struct ite_softc *ip, int flag)
332 {
333 ipriv_t *cci = (ipriv_t *) ip->priv;
334 view_t *v = cci->view;
335 bmap_t *bm = v->bitmap;
336 int dr_plane = (bm->depth > 1 ? bm->depth-1 : 0);
337 int cend, ofs, h, cstart;
338 unsigned char opclr, opset;
339 u_char *pl;
340
341 if (flag == START_CURSOROPT) {
342 if (!cci->cursor_opt) {
343 view_le32n_cursor (ip, ERASE_CURSOR);
344 }
345 cci->cursor_opt++;
346 return; /* if we are already opted. */
347 } else if (flag == END_CURSOROPT) {
348 cci->cursor_opt--;
349
350 }
351
352 if (cci->cursor_opt)
353 return; /* if we are still nested. */
354 /* else we draw the cursor. */
355
356 cstart = 0;
357 cend = ip->ftheight-1;
358 pl = VDISPLAY_LINE (v, dr_plane, (ip->cursory*ip->ftheight+cstart));
359 ofs = (ip->cursorx * ip->ftwidth);
360
361 /* erase cursor */
362 if (flag != DRAW_CURSOR && flag != END_CURSOROPT) {
363 /* erase the cursor */
364 int h;
365 if (dr_plane) {
366 for (h = cend; h >= 0; h--) {
367 asm("bfclr %0@{%1:%2}"
368 : : "a" (pl), "d" (ofs), "d" (ip->ftwidth));
369 pl += cci->row_offset;
370 }
371 } else {
372 for (h = cend; h >= 0; h--) {
373 asm("bfchg %0@{%1:%2}"
374 : : "a" (pl), "d" (ofs), "d" (ip->ftwidth));
375 pl += cci->row_offset;
376 }
377 }
378 }
379
380 if ((flag == DRAW_CURSOR || flag == MOVE_CURSOR || flag == END_CURSOROPT)) {
381
382 ip->cursorx = MIN(ip->curx, ip->cols-1);
383 ip->cursory = ip->cury;
384 cstart = 0;
385 cend = ip->ftheight-1;
386 pl = VDISPLAY_LINE (v, dr_plane, (ip->cursory*ip->ftheight+cstart));
387 ofs = (ip->cursorx * ip->ftwidth);
388
389 /* draw the cursor */
390 if (dr_plane) {
391 for (h = cend; h >= 0; h--) {
392 asm("bfset %0@{%1:%2}"
393 : : "a" (pl), "d" (ofs), "d" (ip->ftwidth));
394 pl += cci->row_offset;
395 }
396 } else {
397 for (h = cend; h >= 0; h--) {
398 asm("bfchg %0@{%1:%2}"
399 : : "a" (pl), "d" (ofs), "d" (ip->ftwidth));
400 pl += cci->row_offset;
401 }
402 }
403 }
404 }
405
406
407 static inline
408 int expbits (int data)
409 {
410 int i, nd = 0;
411 if (data & 1) {
412 nd |= 0x02;
413 }
414 for (i=1; i < 32; i++) {
415 if (data & (1 << i)) {
416 nd |= 0x5 << (i-1);
417 }
418 }
419 nd &= ~data;
420 return (~nd);
421 }
422
423
424 /* Notes: optimizations given the kernel_font_(width|height) #define'd.
425 * the dbra loops could be elminated and unrolled using height,
426 * the :width in the bfxxx instruction could be made immediate instead
427 * of a data register as it now is.
428 * the underline could be added when the loop is unrolled
429 *
430 * It would look like hell but be very fast.*/
431
432 static void
433 putc_nm (cci,p,f,co,ro,fw,fh)
434 register ipriv_t *cci;
435 register u_char *p;
436 register u_char *f;
437 register u_int co;
438 register u_int ro;
439 register u_int fw;
440 register u_int fh;
441 {
442 while (fh--) {
443 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
444 "d" (*f++), "a" (p), "d" (co), "d" (fw));
445 p += ro;
446 }
447 }
448
449 static void
450 putc_in (cci,p,f,co,ro,fw,fh)
451 register ipriv_t *cci;
452 register u_char *p;
453 register u_char *f;
454 register u_int co;
455 register u_int ro;
456 register u_int fw;
457 register u_int fh;
458 {
459 while (fh--) {
460 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
461 "d" (~(*f++)), "a" (p), "d" (co), "d" (fw));
462 p += ro;
463 }
464 }
465
466
467 static void
468 putc_ul (cci,p,f,co,ro,fw,fh)
469 register ipriv_t *cci;
470 register u_char *p;
471 register u_char *f;
472 register u_int co;
473 register u_int ro;
474 register u_int fw;
475 register u_int fh;
476 {
477 int underline = cci->underline;
478 while (underline--) {
479 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
480 "d" (*f++), "a" (p), "d" (co), "d" (fw));
481 p += ro;
482 }
483
484 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
485 "d" (expbits(*f++)), "a" (p), "d" (co), "d" (fw));
486 p += ro;
487
488 underline = fh - cci->underline - 1;
489 while (underline--) {
490 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
491 "d" (*f++), "a" (p), "d" (co), "d" (fw));
492 p += ro;
493 }
494 }
495
496
497 static void
498 putc_ul_in (cci,p,f,co,ro,fw,fh)
499 register ipriv_t *cci;
500 register u_char *p;
501 register u_char *f;
502 register u_int co;
503 register u_int ro;
504 register u_int fw;
505 register u_int fh;
506 {
507 int underline = cci->underline;
508 while (underline--) {
509 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
510 "d" (~(*f++)), "a" (p), "d" (co), "d" (fw));
511 p += ro;
512 }
513
514 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
515 "d" (~expbits(*f++)), "a" (p), "d" (co), "d" (fw));
516 p += ro;
517
518 underline = fh - cci->underline - 1;
519 while (underline--) {
520 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
521 "d" (~(*f++)), "a" (p), "d" (co), "d" (fw));
522 p += ro;
523 }
524 }
525
526 /* bold */
527 static void
528 putc_bd (cci,p,f,co,ro,fw,fh)
529 register ipriv_t *cci;
530 register u_char *p;
531 register u_char *f;
532 register u_int co;
533 register u_int ro;
534 register u_int fw;
535 register u_int fh;
536 {
537 u_word ch;
538
539 while (fh--) {
540 ch = *f++;
541 ch |= ch << 1;
542 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
543 "d" (ch), "a" (p), "d" (co), "d" (fw+1));
544 p += ro;
545 }
546 }
547
548 static void
549 putc_bd_in (cci,p,f,co,ro,fw,fh)
550 register ipriv_t *cci;
551 register u_char *p;
552 register u_char *f;
553 register u_int co;
554 register u_int ro;
555 register u_int fw;
556 register u_int fh;
557 {
558 u_word ch;
559
560 while (fh--) {
561 ch = *f++;
562 ch |= ch << 1;
563 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
564 "d" (~(ch)), "a" (p), "d" (co), "d" (fw+1));
565 p += ro;
566 }
567 }
568
569
570 static void
571 putc_bd_ul (cci,p,f,co,ro,fw,fh)
572 register ipriv_t *cci;
573 register u_char *p;
574 register u_char *f;
575 register u_int co;
576 register u_int ro;
577 register u_int fw;
578 register u_int fh;
579 {
580 int underline = cci->underline;
581 u_word ch;
582
583 while (underline--) {
584 ch = *f++;
585 ch |= ch << 1;
586 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
587 "d" (ch), "a" (p), "d" (co), "d" (fw+1));
588 p += ro;
589 }
590
591 ch = *f++;
592 ch |= ch << 1;
593 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
594 "d" (expbits(ch)), "a" (p), "d" (co), "d" (fw+1));
595 p += ro;
596
597 underline = fh - cci->underline - 1;
598 while (underline--) {
599 ch = *f++;
600 ch |= ch << 1;
601 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
602 "d" (ch), "a" (p), "d" (co), "d" (fw+1));
603 p += ro;
604 }
605 }
606
607
608 static void
609 putc_bd_ul_in (cci,p,f,co,ro,fw,fh)
610 register ipriv_t *cci;
611 register u_char *p;
612 register u_char *f;
613 register u_int co;
614 register u_int ro;
615 register u_int fw;
616 register u_int fh;
617 {
618 int underline = cci->underline;
619 u_word ch;
620
621 while (underline--) {
622 ch = *f++;
623 ch |= ch << 1;
624 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
625 "d" (~(ch)), "a" (p), "d" (co), "d" (fw+1));
626 p += ro;
627 }
628
629 ch = *f++;
630 ch |= ch << 1;
631 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
632 "d" (~expbits(ch)), "a" (p), "d" (co), "d" (fw+1));
633 p += ro;
634
635 underline = fh - cci->underline - 1;
636 while (underline--) {
637 ch = *f++;
638 ch |= ch << 1;
639 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
640 "d" (~(ch)), "a" (p), "d" (co), "d" (fw+1));
641 p += ro;
642 }
643 }
644
645
646 typedef void cc_putc_func ();
647
648 cc_putc_func *put_func[ATTR_ALL+1] = {
649 putc_nm,
650 putc_in,
651 putc_ul,
652 putc_ul_in,
653 putc_bd,
654 putc_bd_in,
655 putc_bd_ul,
656 putc_bd_ul_in,
657 /* no support for blink */
658 putc_nm,
659 putc_in,
660 putc_ul,
661 putc_ul_in,
662 putc_bd,
663 putc_bd_in,
664 putc_bd_ul,
665 putc_bd_ul_in
666 };
667
668
669 /* FIX: shouldn't this advance the cursor even if the character to
670 be output is not available in the font? -ch */
671
672 static void
673 view_le8n_putc(struct ite_softc *ip, int c, int dy, int dx, int mode)
674 {
675 register ipriv_t *cci = (ipriv_t *) ip->priv;
676 if (c < ip->font_lo || c > ip->font_hi)
677 return;
678
679 put_func[mode](cci,
680 cci->row_ptr[dy],
681 cci->font_cell[c],
682 cci->column_offset[dx],
683 cci->row_offset,
684 cci->ft_x,
685 cci->ft_y);
686 }
687
688 static void
689 view_le8n_clear(struct ite_softc *ip, int sy, int sx, int h, int w)
690 {
691 ipriv_t *cci = (ipriv_t *) ip->priv;
692 view_t *v = cci->view;
693 bmap_t *bm = cci->view->bitmap;
694
695 if ((sx == 0) && (w == ip->cols))
696 {
697 /* common case: clearing whole lines */
698 while (h--)
699 {
700 int i;
701 u_char *ptr = cci->row_ptr[sy];
702 for (i=0; i < ip->ftheight; i++) {
703 bzero(ptr, bm->bytes_per_row);
704 ptr += bm->bytes_per_row + bm->row_mod; /* don't get any smart
705 ideas, becuase this is for
706 interleaved bitmaps */
707 }
708 sy++;
709 }
710 }
711 else
712 {
713 /* clearing only part of a line */
714 /* XXX could be optimized MUCH better, but is it worth the trouble? */
715 while (h--)
716 {
717 u_char *pl = cci->row_ptr[sy];
718 int ofs = sx * ip->ftwidth;
719 int i, j;
720 for (i = w-1; i >= 0; i--)
721 {
722 u_char *ppl = pl;
723 for (j = ip->ftheight-1; j >= 0; j--)
724 {
725 asm("bfclr %0@{%1:%2}"
726 : : "a" (ppl), "d" (ofs), "d" (ip->ftwidth));
727 ppl += bm->row_mod + bm->bytes_per_row;
728 }
729 ofs += ip->ftwidth;
730 }
731 sy++;
732 }
733 }
734 }
735
736 /* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT. */
737 static void
738 view_le8n_scroll(ip, sy, sx, count, dir)
739 register struct ite_softc *ip;
740 register int sy;
741 int dir, sx, count;
742 {
743 bmap_t *bm = ((ipriv_t *)ip->priv)->view->bitmap;
744 u_char *pl = ((ipriv_t *)ip->priv)->row_ptr[sy];
745
746 if (dir == SCROLL_UP)
747 {
748 int dy = sy - count;
749 int height = ip->bottom_margin - sy + 1;
750 int i;
751
752 /*FIX: add scroll bitmap call */
753 view_le32n_cursor(ip, ERASE_CURSOR);
754 scroll_bitmap (bm, 0, dy*ip->ftheight,
755 bm->bytes_per_row >> 3, (ip->bottom_margin-dy+1)*ip->ftheight,
756 0, -(count*ip->ftheight), 0x1);
757 /* if (ip->cursory <= bot || ip->cursory >= dy) {
758 ip->cursory -= count;
759 } */
760 }
761 else if (dir == SCROLL_DOWN)
762 {
763 int dy = sy + count;
764 int height = ip->bottom_margin - dy + 1;
765 int i;
766
767 /* FIX: add scroll bitmap call */
768 view_le32n_cursor(ip, ERASE_CURSOR);
769 scroll_bitmap (bm, 0, sy*ip->ftheight,
770 bm->bytes_per_row >> 3, (ip->bottom_margin-sy+1)*ip->ftheight,
771 0, count*ip->ftheight, 0x1);
772 /* if (ip->cursory <= bot || ip->cursory >= sy) {
773 ip->cursory += count;
774 } */
775 }
776 else if (dir == SCROLL_RIGHT)
777 {
778 int sofs = (ip->cols - count) * ip->ftwidth;
779 int dofs = (ip->cols) * ip->ftwidth;
780 int i, j;
781
782 view_le32n_cursor(ip, ERASE_CURSOR);
783 for (j = ip->ftheight-1; j >= 0; j--)
784 {
785 int sofs2 = sofs, dofs2 = dofs;
786 for (i = (ip->cols - (sx + count))-1; i >= 0; i--)
787 {
788 int t;
789 sofs2 -= ip->ftwidth;
790 dofs2 -= ip->ftwidth;
791 asm("bfextu %1@{%2:%3},%0"
792 : "=d" (t)
793 : "a" (pl), "d" (sofs2), "d" (ip->ftwidth));
794 asm("bfins %3,%0@{%1:%2}"
795 : : "a" (pl), "d" (dofs2), "d" (ip->ftwidth), "d" (t));
796 }
797 pl += bm->row_mod + bm->bytes_per_row;
798 }
799 }
800 else /* SCROLL_LEFT */
801 {
802 int sofs = (sx) * ip->ftwidth;
803 int dofs = (sx - count) * ip->ftwidth;
804 int i, j;
805
806 view_le32n_cursor(ip, ERASE_CURSOR);
807 for (j = ip->ftheight-1; j >= 0; j--)
808 {
809 int sofs2 = sofs, dofs2 = dofs;
810 for (i = (ip->cols - sx)-1; i >= 0; i--)
811 {
812 int t;
813 asm("bfextu %1@{%2:%3},%0"
814 : "=d" (t)
815 : "a" (pl), "d" (sofs2), "d" (ip->ftwidth));
816 asm("bfins %3,%0@{%1:%2}"
817 : : "a" (pl), "d" (dofs2), "d" (ip->ftwidth), "d" (t));
818 sofs2 += ip->ftwidth;
819 dofs2 += ip->ftwidth;
820 }
821 pl += bm->row_mod + bm->bytes_per_row;
822 }
823 }
824 }
825
826 void
827 scroll_bitmap (bmap_t *bm, u_word x, u_word y, u_word width, u_word height, word dx, word dy, u_byte mask)
828 {
829 u_word depth = bm->depth;
830 u_word lwpr = bm->bytes_per_row >> 2;
831 if (dx) {
832 /* FIX: */ panic ("delta x not supported in scroll bitmap yet.");
833 }
834 if (bm->flags & BMF_INTERLEAVED) {
835 height *= depth;
836 depth = 1;
837 }
838 if (dy == 0) {
839 return;
840 }
841 if (dy > 0) {
842 int i;
843 for (i=0; i < depth && mask; i++, mask >>= 1) {
844 if (0x1 & mask) {
845 u_long *pl = (u_long *)bm->plane[i];
846 u_long *src_y = pl + (lwpr*y);
847 u_long *dest_y = pl + (lwpr*(y+dy));
848 u_long count = lwpr*(height-dy);
849 u_long *clr_y = src_y;
850 u_long clr_count = dest_y - src_y;
851 u_long bc, cbc;
852
853 src_y += count - 1;
854 dest_y += count - 1;
855
856 bc = count >> 4;
857 count &= 0xf;
858
859 while (bc--) {
860 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
861 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
862 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
863 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
864 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
865 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
866 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
867 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
868 }
869 while (count--) {
870 *dest_y-- = *src_y--;
871 }
872
873 cbc = clr_count >> 4;
874 clr_count &= 0xf;
875
876 while (cbc--) {
877 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
878 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
879 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
880 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
881 }
882 while (clr_count--) {
883 *clr_y++ = 0;
884 }
885 }
886 }
887 } else if (dy < 0) {
888 int i;
889 for (i=0; i < depth && mask; i++, mask >>= 1) {
890 if (0x1 & mask) {
891 u_long *pl = (u_long *)bm->plane[i];
892 u_long *src_y = pl + (lwpr*(y-dy));
893 u_long *dest_y = pl + (lwpr*y);
894 long count = lwpr*(height + dy);
895 u_long *clr_y = dest_y + count;
896 u_long clr_count = src_y - dest_y;
897 u_long bc, cbc;
898
899 bc = count >> 4;
900 count &= 0xf;
901
902 while (bc--) {
903 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
904 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
905 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
906 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
907 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
908 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
909 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
910 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
911 }
912 while (count--) {
913 *dest_y++ = *src_y++;
914 }
915
916 cbc = clr_count >> 4;
917 clr_count &= 0xf;
918
919 while (cbc--) {
920 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
921 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
922 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
923 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
924 }
925 while (clr_count--) {
926 *clr_y++ = 0;
927 }
928 }
929 }
930 }
931 }
932 #endif
933