Fix use of uninitialized memory in xlcd_scroll_left() / xlcd_scroll_right() in specia...
[maemo-rb.git] / apps / plugins / lib / xlcd_scroll.c
blob8f55f4153ea2457de676e3a574b21cae00b79431
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Additional LCD routines not present in the rockbox core
11 * Scrolling functions
13 * Copyright (C) 2005 Jens Arnold
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
25 #include "plugin.h"
27 #include "xlcd.h"
29 #if (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
30 static const unsigned short patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
31 #endif
33 #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
34 void xlcd_scroll_left(int count)
36 int length, oldmode;
38 if ((unsigned)count >= LCD_WIDTH)
40 rb->lcd_clear_display();
41 return;
44 length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
46 rb->memmove(rb->lcd_framebuffer, rb->lcd_framebuffer + LCD_HEIGHT*count,
47 length * sizeof(fb_data));
49 oldmode = rb->lcd_get_drawmode();
50 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
51 rb->lcd_fillrect(LCD_WIDTH-count, 0, count, LCD_HEIGHT);
52 rb->lcd_set_drawmode(oldmode);
55 /* Scroll right */
56 void xlcd_scroll_right(int count)
58 int length, oldmode;
60 if ((unsigned)count >= LCD_WIDTH)
62 rb->lcd_clear_display();
63 return;
66 length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
68 rb->memmove(rb->lcd_framebuffer + LCD_HEIGHT*count,
69 rb->lcd_framebuffer, length * sizeof(fb_data));
71 oldmode = rb->lcd_get_drawmode();
72 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
73 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
74 rb->lcd_set_drawmode(oldmode);
77 /* Scroll up */
78 void xlcd_scroll_up(int count)
80 int width, length, oldmode;
82 fb_data *data;
84 if ((unsigned)count >= LCD_HEIGHT)
86 rb->lcd_clear_display();
87 return;
90 length = LCD_HEIGHT - count;
92 width = LCD_WIDTH-1;
93 data = rb->lcd_framebuffer;
95 do {
96 rb->memmove(data,data + count,length * sizeof(fb_data));
97 data += LCD_HEIGHT;
98 } while(width--);
100 oldmode = rb->lcd_get_drawmode();
101 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
102 rb->lcd_fillrect(0, length, LCD_WIDTH, count);
103 rb->lcd_set_drawmode(oldmode);
106 /* Scroll down */
107 void xlcd_scroll_down(int count)
109 int width, length, oldmode;
111 fb_data *data;
113 if ((unsigned)count >= LCD_HEIGHT)
115 rb->lcd_clear_display();
116 return;
119 length = LCD_HEIGHT - count;
121 width = LCD_WIDTH-1;
122 data = rb->lcd_framebuffer;
124 do {
125 rb->memmove(data + count, data, length * sizeof(fb_data));
126 data += LCD_HEIGHT;
127 } while(width--);
129 oldmode = rb->lcd_get_drawmode();
130 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
131 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
132 rb->lcd_set_drawmode(oldmode);
134 #else
136 #if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) && (LCD_DEPTH < 8)
138 /* Scroll left */
139 void xlcd_scroll_left(int count)
141 int bitcount=0, oldmode;
142 int blockcount=0, blocklen;
144 if ((unsigned) count >= LCD_WIDTH)
146 rb->lcd_clear_display();
147 return;
150 #if LCD_DEPTH == 2
151 blockcount = count >> 2;
152 blocklen = LCD_FBWIDTH - blockcount;
153 bitcount = 2 * (count & 3);
154 #endif
156 if (blockcount)
158 unsigned char *data = rb->lcd_framebuffer;
159 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
163 rb->memmove(data, data + blockcount, blocklen);
164 data += LCD_FBWIDTH;
166 while (data < data_end);
168 if (bitcount)
170 int bx, y;
171 unsigned char *addr = rb->lcd_framebuffer + blocklen;
172 #if LCD_DEPTH == 2
173 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
174 #endif
176 for (y = 0; y < LCD_HEIGHT; y++)
178 unsigned char *row_addr = addr;
179 unsigned data = fill;
181 for (bx = 0; bx < blocklen; bx++)
183 --row_addr;
184 data = (data >> 8) | (*row_addr << bitcount);
185 *row_addr = data;
187 addr += LCD_FBWIDTH;
190 oldmode = rb->lcd_get_drawmode();
191 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
192 rb->lcd_fillrect(LCD_WIDTH - count, 0, count, LCD_HEIGHT);
193 rb->lcd_set_drawmode(oldmode);
196 /* Scroll right */
197 void xlcd_scroll_right(int count)
199 int bitcount=0, oldmode;
200 int blockcount=0, blocklen;
202 if ((unsigned) count >= LCD_WIDTH)
204 rb->lcd_clear_display();
205 return;
208 #if LCD_DEPTH == 2
209 blockcount = count >> 2;
210 blocklen = LCD_FBWIDTH - blockcount;
211 bitcount = 2 * (count & 3);
212 #endif
214 if (blockcount)
216 unsigned char *data = rb->lcd_framebuffer;
217 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
221 rb->memmove(data + blockcount, data, blocklen);
222 data += LCD_FBWIDTH;
224 while (data < data_end);
226 if (bitcount)
228 int bx, y;
229 unsigned char *addr = rb->lcd_framebuffer + blockcount;
230 #if LCD_DEPTH == 2
231 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
232 #endif
234 for (y = 0; y < LCD_HEIGHT; y++)
236 unsigned char *row_addr = addr;
237 unsigned data = fill;
239 for (bx = 0; bx < blocklen; bx++)
241 data = (data << 8) | *row_addr;
242 *row_addr = data >> bitcount;
243 row_addr++;
245 addr += LCD_FBWIDTH;
248 oldmode = rb->lcd_get_drawmode();
249 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
250 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
251 rb->lcd_set_drawmode(oldmode);
254 #else /* LCD_PIXELFORMAT vertical packed or >= 8bit / pixel */
256 /* Scroll left */
257 void xlcd_scroll_left(int count)
259 fb_data *data, *data_end;
260 int length, oldmode;
262 if ((unsigned)count >= LCD_WIDTH)
264 rb->lcd_clear_display();
265 return;
268 data = rb->lcd_framebuffer;
269 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
270 length = LCD_WIDTH - count;
274 rb->memmove(data, data + count, length * sizeof(fb_data));
275 data += LCD_WIDTH;
277 while (data < data_end);
279 oldmode = rb->lcd_get_drawmode();
280 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
281 rb->lcd_fillrect(length, 0, count, LCD_HEIGHT);
282 rb->lcd_set_drawmode(oldmode);
285 /* Scroll right */
286 void xlcd_scroll_right(int count)
288 fb_data *data, *data_end;
289 int length, oldmode;
291 if ((unsigned)count >= LCD_WIDTH)
293 rb->lcd_clear_display();
294 return;
297 data = rb->lcd_framebuffer;
298 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
299 length = LCD_WIDTH - count;
303 rb->memmove(data + count, data, length * sizeof(fb_data));
304 data += LCD_WIDTH;
306 while (data < data_end);
308 oldmode = rb->lcd_get_drawmode();
309 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
310 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
311 rb->lcd_set_drawmode(oldmode);
314 #endif /* LCD_PIXELFORMAT, LCD_DEPTH */
316 #if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) || (LCD_DEPTH >= 8)
318 /* Scroll up */
319 void xlcd_scroll_up(int count)
321 int length, oldmode;
323 if ((unsigned)count >= LCD_HEIGHT)
325 rb->lcd_clear_display();
326 return;
329 length = LCD_HEIGHT - count;
331 rb->memmove(rb->lcd_framebuffer,
332 rb->lcd_framebuffer + count * LCD_FBWIDTH,
333 length * LCD_FBWIDTH * sizeof(fb_data));
335 oldmode = rb->lcd_get_drawmode();
336 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
337 rb->lcd_fillrect(0, length, LCD_WIDTH, count);
338 rb->lcd_set_drawmode(oldmode);
341 /* Scroll down */
342 void xlcd_scroll_down(int count)
344 int length, oldmode;
346 if ((unsigned)count >= LCD_HEIGHT)
348 rb->lcd_clear_display();
349 return;
352 length = LCD_HEIGHT - count;
354 rb->memmove(rb->lcd_framebuffer + count * LCD_FBWIDTH,
355 rb->lcd_framebuffer,
356 length * LCD_FBWIDTH * sizeof(fb_data));
358 oldmode = rb->lcd_get_drawmode();
359 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
360 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
361 rb->lcd_set_drawmode(oldmode);
364 #else /* LCD_PIXELFORMAT == VERTICAL_PACKING,
365 LCD_PIXELFORMAT == VERTICAL_INTERLEAVED */
367 /* Scroll up */
368 void xlcd_scroll_up(int count)
370 int bitcount, oldmode;
371 int blockcount, blocklen;
373 if ((unsigned) count >= LCD_HEIGHT)
375 rb->lcd_clear_display();
376 return;
379 #if (LCD_DEPTH == 1) \
380 || (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
381 blockcount = count >> 3;
382 bitcount = count & 7;
383 #elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
384 blockcount = count >> 2;
385 bitcount = 2 * (count & 3);
386 #endif
387 blocklen = LCD_FBHEIGHT - blockcount;
389 if (blockcount)
391 rb->memmove(rb->lcd_framebuffer,
392 rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
393 blocklen * LCD_FBWIDTH * sizeof(fb_data));
395 if (bitcount)
397 #if LCD_PIXELFORMAT == VERTICAL_PACKING
399 #if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
400 asm (
401 "mov #0,r4 \n" /* x = 0 */
402 "mova .su_shifttbl,r0 \n" /* calculate jump destination for */
403 "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
404 "bra .su_cloop \n" /* skip table */
405 "add r0,%[cnt] \n"
407 ".align 2 \n"
408 ".su_shifttbl: \n" /* shift jump offset table */
409 ".byte .su_shift0 - .su_shifttbl \n"
410 ".byte .su_shift1 - .su_shifttbl \n"
411 ".byte .su_shift2 - .su_shifttbl \n"
412 ".byte .su_shift3 - .su_shifttbl \n"
413 ".byte .su_shift4 - .su_shifttbl \n"
414 ".byte .su_shift5 - .su_shifttbl \n"
415 ".byte .su_shift6 - .su_shifttbl \n"
416 ".byte .su_shift7 - .su_shifttbl \n"
418 ".su_cloop: \n" /* repeat for every column */
419 "mov %[addr],r2 \n" /* get start address */
420 "mov #0,r3 \n" /* current_row = 0 */
421 "mov #0,r1 \n" /* fill with zero */
423 ".su_iloop: \n" /* repeat for all rows */
424 "sub %[wide],r2 \n" /* address -= width */
425 "mov.b @r2,r0 \n" /* get data byte */
426 "shll8 r1 \n" /* old data to 2nd byte */
427 "extu.b r0,r0 \n" /* extend unsigned */
428 "or r1,r0 \n" /* combine old data */
429 "jmp @%[cnt] \n" /* jump into shift "path" */
430 "extu.b r0,r1 \n" /* store data for next round */
432 ".su_shift6: \n" /* shift right by 0..7 bits */
433 "shll2 r0 \n"
434 "bra .su_shift0 \n"
435 "shlr8 r0 \n"
436 ".su_shift4: \n"
437 "shlr2 r0 \n"
438 ".su_shift2: \n"
439 "bra .su_shift0 \n"
440 "shlr2 r0 \n"
441 ".su_shift7: \n"
442 "shlr2 r0 \n"
443 ".su_shift5: \n"
444 "shlr2 r0 \n"
445 ".su_shift3: \n"
446 "shlr2 r0 \n"
447 ".su_shift1: \n"
448 "shlr r0 \n"
449 ".su_shift0: \n"
451 "mov.b r0,@r2 \n" /* store data */
452 "add #1,r3 \n" /* current_row++ */
453 "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
454 "bt .su_iloop \n"
456 "add #1,%[addr] \n" /* start_address++ */
457 "add #1,r4 \n" /* x++ */
458 "cmp/hi r4,%[wide] \n" /* x < width ? */
459 "bt .su_cloop \n"
460 : /* outputs */
461 : /* inputs */
462 [addr]"r"(rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
463 [wide]"r"(LCD_FBWIDTH),
464 [rows]"r"(blocklen),
465 [cnt] "r"(bitcount)
466 : /* clobbers */
467 "r0", "r1", "r2", "r3", "r4"
469 #elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
470 asm (
471 "move.l %[wide],%%d3\n" /* columns = width */
473 ".su_cloop: \n" /* repeat for every column */
474 "move.l %[addr],%%a1\n" /* get start address */
475 "move.l %[rows],%%d2\n" /* rows = row_count */
476 "move.l %[bkg],%%d1 \n" /* fill with background */
478 ".su_iloop: \n" /* repeat for all rows */
479 "sub.l %[wide],%%a1\n" /* address -= width */
481 "lsl.l #8,%%d1 \n" /* old data to 2nd byte */
482 "move.b (%%a1),%%d1 \n" /* combine with new data byte */
483 "move.l %%d1,%%d0 \n" /* keep data for next round */
484 "lsr.l %[cnt],%%d0 \n" /* shift right */
485 "move.b %%d0,(%%a1) \n" /* store data */
487 "subq.l #1,%%d2 \n" /* rows-- */
488 "bne.b .su_iloop \n"
490 "addq.l #1,%[addr] \n" /* start_address++ */
491 "subq.l #1,%%d3 \n" /* columns-- */
492 "bne.b .su_cloop \n"
493 : /* outputs */
494 : /* inputs */
495 [wide]"r"(LCD_FBWIDTH),
496 [rows]"r"(blocklen),
497 [addr]"a"(rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
498 [cnt] "d"(bitcount),
499 [bkg] "d"(0x55 * (~rb->lcd_get_background() & 3))
500 : /* clobbers */
501 "a1", "d0", "d1", "d2", "d3"
503 #else /* C version */
504 int x, by;
505 unsigned char *addr = rb->lcd_framebuffer + blocklen * LCD_FBWIDTH;
506 #if LCD_DEPTH == 2
507 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
508 #else
509 const unsigned fill = 0;
510 #endif
512 for (x = 0; x < LCD_WIDTH; x++)
514 unsigned char *col_addr = addr++;
515 unsigned data = fill;
517 for (by = 0; by < blocklen; by++)
519 col_addr -= LCD_FBWIDTH;
520 data = (data << 8) | *col_addr;
521 *col_addr = data >> bitcount;
524 #endif /* CPU, LCD_DEPTH */
526 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
528 #if LCD_DEPTH == 2
529 int x, by;
530 fb_data *addr = rb->lcd_framebuffer + blocklen * LCD_FBWIDTH;
531 unsigned fill, mask;
533 fill = patterns[rb->lcd_get_background() & 3] << 8;
534 mask = (0xFFu >> bitcount) << bitcount;
535 mask |= mask << 8;
537 for (x = 0; x < LCD_WIDTH; x++)
539 fb_data *col_addr = addr++;
540 unsigned olddata = fill;
541 unsigned data;
543 for (by = 0; by < blocklen; by++)
545 col_addr -= LCD_FBWIDTH;
546 data = *col_addr;
547 *col_addr = (olddata ^ ((data ^ olddata) & mask)) >> bitcount;
548 olddata = data << 8;
551 #endif /* LCD_DEPTH == 2 */
553 #endif /* LCD_PIXELFORMAT */
555 oldmode = rb->lcd_get_drawmode();
556 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
557 rb->lcd_fillrect(0, LCD_HEIGHT - count, LCD_WIDTH, count);
558 rb->lcd_set_drawmode(oldmode);
561 /* Scroll up */
562 void xlcd_scroll_down(int count)
564 int bitcount, oldmode;
565 int blockcount, blocklen;
567 if ((unsigned) count >= LCD_HEIGHT)
569 rb->lcd_clear_display();
570 return;
573 #if (LCD_DEPTH == 1) \
574 || (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
575 blockcount = count >> 3;
576 bitcount = count & 7;
577 #elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
578 blockcount = count >> 2;
579 bitcount = 2 * (count & 3);
580 #endif
581 blocklen = LCD_FBHEIGHT - blockcount;
583 if (blockcount)
585 rb->memmove(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
586 rb->lcd_framebuffer,
587 blocklen * LCD_FBWIDTH * sizeof(fb_data));
589 if (bitcount)
591 #if LCD_PIXELFORMAT == VERTICAL_PACKING
593 #if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
594 asm (
595 "mov #0,r4 \n" /* x = 0 */
596 "mova .sd_shifttbl,r0 \n" /* calculate jump destination for */
597 "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
598 "bra .sd_cloop \n" /* skip table */
599 "add r0,%[cnt] \n"
601 ".align 2 \n"
602 ".sd_shifttbl: \n" /* shift jump offset table */
603 ".byte .sd_shift0 - .sd_shifttbl \n"
604 ".byte .sd_shift1 - .sd_shifttbl \n"
605 ".byte .sd_shift2 - .sd_shifttbl \n"
606 ".byte .sd_shift3 - .sd_shifttbl \n"
607 ".byte .sd_shift4 - .sd_shifttbl \n"
608 ".byte .sd_shift5 - .sd_shifttbl \n"
609 ".byte .sd_shift6 - .sd_shifttbl \n"
610 ".byte .sd_shift7 - .sd_shifttbl \n"
612 ".sd_cloop: \n" /* repeat for every column */
613 "mov %[addr],r2 \n" /* get start address */
614 "mov #0,r3 \n" /* current_row = 0 */
615 "mov #0,r1 \n" /* fill with zero */
617 ".sd_iloop: \n" /* repeat for all rows */
618 "shlr8 r1 \n" /* shift right to get residue */
619 "mov.b @r2,r0 \n" /* get data byte */
620 "jmp @%[cnt] \n" /* jump into shift "path" */
621 "extu.b r0,r0 \n" /* extend unsigned */
623 ".sd_shift6: \n" /* shift left by 0..7 bits */
624 "shll8 r0 \n"
625 "bra .sd_shift0 \n"
626 "shlr2 r0 \n"
627 ".sd_shift4: \n"
628 "shll2 r0 \n"
629 ".sd_shift2: \n"
630 "bra .sd_shift0 \n"
631 "shll2 r0 \n"
632 ".sd_shift7: \n"
633 "shll2 r0 \n"
634 ".sd_shift5: \n"
635 "shll2 r0 \n"
636 ".sd_shift3: \n"
637 "shll2 r0 \n"
638 ".sd_shift1: \n"
639 "shll r0 \n"
640 ".sd_shift0: \n"
642 "or r0,r1 \n" /* combine with last residue */
643 "mov.b r1,@r2 \n" /* store data */
644 "add %[wide],r2 \n" /* address += width */
645 "add #1,r3 \n" /* current_row++ */
646 "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
647 "bt .sd_iloop \n"
649 "add #1,%[addr] \n" /* start_address++ */
650 "add #1,r4 \n" /* x++ */
651 "cmp/hi r4,%[wide] \n" /* x < width ? */
652 "bt .sd_cloop \n"
653 : /* outputs */
654 : /* inputs */
655 [addr]"r"(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
656 [wide]"r"(LCD_WIDTH),
657 [rows]"r"(blocklen),
658 [cnt] "r"(bitcount)
659 : /* clobbers */
660 "r0", "r1", "r2", "r3", "r4"
662 #elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
663 asm (
664 "move.l %[wide],%%d3\n" /* columns = width */
666 ".sd_cloop: \n" /* repeat for every column */
667 "move.l %[addr],%%a1\n" /* get start address */
668 "move.l %[rows],%%d2\n" /* rows = row_count */
669 "move.l %[bkg],%%d1 \n" /* fill with background */
671 ".sd_iloop: \n" /* repeat for all rows */
672 "lsr.l #8,%%d1 \n" /* shift right to get residue */
673 "clr.l %%d0 \n"
674 "move.b (%%a1),%%d0 \n" /* get data byte */
675 "lsl.l %[cnt],%%d0 \n"
676 "or.l %%d0,%%d1 \n" /* combine with last residue */
677 "move.b %%d1,(%%a1) \n" /* store data */
679 "add.l %[wide],%%a1\n" /* address += width */
680 "subq.l #1,%%d2 \n" /* rows-- */
681 "bne.b .sd_iloop \n"
683 "lea.l (1,%[addr]),%[addr] \n" /* start_address++ */
684 "subq.l #1,%%d3 \n" /* columns-- */
685 "bne.b .sd_cloop \n"
686 : /* outputs */
687 : /* inputs */
688 [wide]"r"(LCD_WIDTH),
689 [rows]"r"(blocklen),
690 [addr]"a"(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
691 [cnt] "d"(bitcount),
692 [bkg] "d"((0x55 * (~rb->lcd_get_background() & 3)) << bitcount)
693 : /* clobbers */
694 "a1", "d0", "d1", "d2", "d3"
696 #else /* C version */
697 int x, by;
698 unsigned char *addr = rb->lcd_framebuffer + blockcount * LCD_FBWIDTH;
699 #if LCD_DEPTH == 2
700 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
701 #else
702 const unsigned fill = 0;
703 #endif
705 for (x = 0; x < LCD_WIDTH; x++)
707 unsigned char *col_addr = addr++;
708 unsigned data = fill;
710 for (by = 0; by < blocklen; by++)
712 data = (data >> 8) | (*col_addr << bitcount);
713 *col_addr = data;
714 col_addr += LCD_FBWIDTH;
717 #endif /* CPU, LCD_DEPTH */
719 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
721 #if LCD_DEPTH == 2
722 int x, by;
723 fb_data *addr = rb->lcd_framebuffer + blockcount * LCD_FBWIDTH;
724 unsigned fill, mask;
726 fill = patterns[rb->lcd_get_background() & 3] >> (8 - bitcount);
727 mask = (0xFFu >> bitcount) << bitcount;
728 mask |= mask << 8;
730 for (x = 0; x < LCD_WIDTH; x++)
732 fb_data *col_addr = addr++;
733 unsigned olddata = fill;
734 unsigned data;
736 for (by = 0; by < blocklen; by++)
738 data = *col_addr << bitcount;
739 *col_addr = olddata ^ ((data ^ olddata) & mask);
740 olddata = data >> 8;
741 col_addr += LCD_FBWIDTH;
744 #endif /* LCD_DEPTH == 2 */
746 #endif /* LCD_PIXELFORMAT */
748 oldmode = rb->lcd_get_drawmode();
749 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
750 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
751 rb->lcd_set_drawmode(oldmode);
754 #endif /* LCD_PIXELFORMAT, LCD_DEPTH */
755 #endif /* defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE */