Move the PCM/audio playback part of SDL into the target tree.
[kugel-rb.git] / apps / plugins / lib / xlcd_scroll.c
blob0d06545c849a767ff1924c1631fe7248d111743b
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 #ifdef HAVE_LCD_BITMAP
28 #include "xlcd.h"
30 #if (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
31 static const unsigned short patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
32 #endif
34 #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
35 void xlcd_scroll_left(int count)
37 int length, oldmode;
39 if ((unsigned)count >= LCD_WIDTH)
41 rb->lcd_clear_display();
42 return;
45 length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
47 rb->memmove(rb->lcd_framebuffer, rb->lcd_framebuffer + LCD_HEIGHT*count,
48 length * sizeof(fb_data));
50 oldmode = rb->lcd_get_drawmode();
51 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
52 rb->lcd_fillrect(LCD_WIDTH-count, 0, count, LCD_HEIGHT);
53 rb->lcd_set_drawmode(oldmode);
56 /* Scroll right */
57 void xlcd_scroll_right(int count)
59 int length, oldmode;
61 if ((unsigned)count >= LCD_WIDTH)
63 rb->lcd_clear_display();
64 return;
67 length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
69 rb->memmove(rb->lcd_framebuffer + LCD_HEIGHT*count,
70 rb->lcd_framebuffer, length * sizeof(fb_data));
72 oldmode = rb->lcd_get_drawmode();
73 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
74 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
75 rb->lcd_set_drawmode(oldmode);
78 /* Scroll up */
79 void xlcd_scroll_up(int count)
81 int width, length, oldmode;
83 fb_data *data;
85 if ((unsigned)count >= LCD_HEIGHT)
87 rb->lcd_clear_display();
88 return;
91 length = LCD_HEIGHT - count;
93 width = LCD_WIDTH-1;
94 data = rb->lcd_framebuffer;
96 do {
97 rb->memmove(data,data + count,length * sizeof(fb_data));
98 data += LCD_HEIGHT;
99 } while(width--);
101 oldmode = rb->lcd_get_drawmode();
102 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
103 rb->lcd_fillrect(0, length, LCD_WIDTH, count);
104 rb->lcd_set_drawmode(oldmode);
107 /* Scroll down */
108 void xlcd_scroll_down(int count)
110 int width, length, oldmode;
112 fb_data *data;
114 if ((unsigned)count >= LCD_HEIGHT)
116 rb->lcd_clear_display();
117 return;
120 length = LCD_HEIGHT - count;
122 width = LCD_WIDTH-1;
123 data = rb->lcd_framebuffer;
125 do {
126 rb->memmove(data + count, data, length * sizeof(fb_data));
127 data += LCD_HEIGHT;
128 } while(width--);
130 oldmode = rb->lcd_get_drawmode();
131 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
132 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
133 rb->lcd_set_drawmode(oldmode);
135 #else
137 #if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) && (LCD_DEPTH < 8)
139 /* Scroll left */
140 void xlcd_scroll_left(int count)
142 int bitcount, oldmode;
143 int blockcount, blocklen;
145 if ((unsigned) count >= LCD_WIDTH)
147 rb->lcd_clear_display();
148 return;
151 #if LCD_DEPTH == 2
152 blockcount = count >> 2;
153 blocklen = LCD_FBWIDTH - blockcount;
154 bitcount = 2 * (count & 3);
155 #endif
157 if (blockcount)
159 unsigned char *data = rb->lcd_framebuffer;
160 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
164 rb->memmove(data, data + blockcount, blocklen);
165 data += LCD_FBWIDTH;
167 while (data < data_end);
169 if (bitcount)
171 int bx, y;
172 unsigned char *addr = rb->lcd_framebuffer + blocklen;
173 #if LCD_DEPTH == 2
174 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
175 #endif
177 for (y = 0; y < LCD_HEIGHT; y++)
179 unsigned char *row_addr = addr;
180 unsigned data = fill;
182 for (bx = 0; bx < blocklen; bx++)
184 --row_addr;
185 data = (data >> 8) | (*row_addr << bitcount);
186 *row_addr = data;
188 addr += LCD_FBWIDTH;
191 oldmode = rb->lcd_get_drawmode();
192 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
193 rb->lcd_fillrect(LCD_WIDTH - count, 0, count, LCD_HEIGHT);
194 rb->lcd_set_drawmode(oldmode);
197 /* Scroll right */
198 void xlcd_scroll_right(int count)
200 int bitcount, oldmode;
201 int blockcount, blocklen;
203 if ((unsigned) count >= LCD_WIDTH)
205 rb->lcd_clear_display();
206 return;
209 #if LCD_DEPTH == 2
210 blockcount = count >> 2;
211 blocklen = LCD_FBWIDTH - blockcount;
212 bitcount = 2 * (count & 3);
213 #endif
215 if (blockcount)
217 unsigned char *data = rb->lcd_framebuffer;
218 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
222 rb->memmove(data + blockcount, data, blocklen);
223 data += LCD_FBWIDTH;
225 while (data < data_end);
227 if (bitcount)
229 int bx, y;
230 unsigned char *addr = rb->lcd_framebuffer + blockcount;
231 #if LCD_DEPTH == 2
232 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
233 #endif
235 for (y = 0; y < LCD_HEIGHT; y++)
237 unsigned char *row_addr = addr;
238 unsigned data = fill;
240 for (bx = 0; bx < blocklen; bx++)
242 data = (data << 8) | *row_addr;
243 *row_addr = data >> bitcount;
244 row_addr++;
246 addr += LCD_FBWIDTH;
249 oldmode = rb->lcd_get_drawmode();
250 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
251 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
252 rb->lcd_set_drawmode(oldmode);
255 #else /* LCD_PIXELFORMAT vertical packed or >= 8bit / pixel */
257 /* Scroll left */
258 void xlcd_scroll_left(int count)
260 fb_data *data, *data_end;
261 int length, oldmode;
263 if ((unsigned)count >= LCD_WIDTH)
265 rb->lcd_clear_display();
266 return;
269 data = rb->lcd_framebuffer;
270 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
271 length = LCD_WIDTH - count;
275 rb->memmove(data, data + count, length * sizeof(fb_data));
276 data += LCD_WIDTH;
278 while (data < data_end);
280 oldmode = rb->lcd_get_drawmode();
281 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
282 rb->lcd_fillrect(length, 0, count, LCD_HEIGHT);
283 rb->lcd_set_drawmode(oldmode);
286 /* Scroll right */
287 void xlcd_scroll_right(int count)
289 fb_data *data, *data_end;
290 int length, oldmode;
292 if ((unsigned)count >= LCD_WIDTH)
294 rb->lcd_clear_display();
295 return;
298 data = rb->lcd_framebuffer;
299 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
300 length = LCD_WIDTH - count;
304 rb->memmove(data + count, data, length * sizeof(fb_data));
305 data += LCD_WIDTH;
307 while (data < data_end);
309 oldmode = rb->lcd_get_drawmode();
310 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
311 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
312 rb->lcd_set_drawmode(oldmode);
315 #endif /* LCD_PIXELFORMAT, LCD_DEPTH */
317 #if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) || (LCD_DEPTH >= 8)
319 /* Scroll up */
320 void xlcd_scroll_up(int count)
322 int length, oldmode;
324 if ((unsigned)count >= LCD_HEIGHT)
326 rb->lcd_clear_display();
327 return;
330 length = LCD_HEIGHT - count;
332 rb->memmove(rb->lcd_framebuffer,
333 rb->lcd_framebuffer + count * LCD_FBWIDTH,
334 length * LCD_FBWIDTH * sizeof(fb_data));
336 oldmode = rb->lcd_get_drawmode();
337 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
338 rb->lcd_fillrect(0, length, LCD_WIDTH, count);
339 rb->lcd_set_drawmode(oldmode);
342 /* Scroll down */
343 void xlcd_scroll_down(int count)
345 int length, oldmode;
347 if ((unsigned)count >= LCD_HEIGHT)
349 rb->lcd_clear_display();
350 return;
353 length = LCD_HEIGHT - count;
355 rb->memmove(rb->lcd_framebuffer + count * LCD_FBWIDTH,
356 rb->lcd_framebuffer,
357 length * LCD_FBWIDTH * sizeof(fb_data));
359 oldmode = rb->lcd_get_drawmode();
360 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
361 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
362 rb->lcd_set_drawmode(oldmode);
365 #else /* LCD_PIXELFORMAT == VERTICAL_PACKING,
366 LCD_PIXELFORMAT == VERTICAL_INTERLEAVED */
368 /* Scroll up */
369 void xlcd_scroll_up(int count)
371 int bitcount, oldmode;
372 int blockcount, blocklen;
374 if ((unsigned) count >= LCD_HEIGHT)
376 rb->lcd_clear_display();
377 return;
380 #if (LCD_DEPTH == 1) \
381 || (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
382 blockcount = count >> 3;
383 bitcount = count & 7;
384 #elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
385 blockcount = count >> 2;
386 bitcount = 2 * (count & 3);
387 #endif
388 blocklen = LCD_FBHEIGHT - blockcount;
390 if (blockcount)
392 rb->memmove(rb->lcd_framebuffer,
393 rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
394 blocklen * LCD_FBWIDTH * sizeof(fb_data));
396 if (bitcount)
398 #if LCD_PIXELFORMAT == VERTICAL_PACKING
400 #if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
401 asm (
402 "mov #0,r4 \n" /* x = 0 */
403 "mova .su_shifttbl,r0 \n" /* calculate jump destination for */
404 "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
405 "bra .su_cloop \n" /* skip table */
406 "add r0,%[cnt] \n"
408 ".align 2 \n"
409 ".su_shifttbl: \n" /* shift jump offset table */
410 ".byte .su_shift0 - .su_shifttbl \n"
411 ".byte .su_shift1 - .su_shifttbl \n"
412 ".byte .su_shift2 - .su_shifttbl \n"
413 ".byte .su_shift3 - .su_shifttbl \n"
414 ".byte .su_shift4 - .su_shifttbl \n"
415 ".byte .su_shift5 - .su_shifttbl \n"
416 ".byte .su_shift6 - .su_shifttbl \n"
417 ".byte .su_shift7 - .su_shifttbl \n"
419 ".su_cloop: \n" /* repeat for every column */
420 "mov %[addr],r2 \n" /* get start address */
421 "mov #0,r3 \n" /* current_row = 0 */
422 "mov #0,r1 \n" /* fill with zero */
424 ".su_iloop: \n" /* repeat for all rows */
425 "sub %[wide],r2 \n" /* address -= width */
426 "mov.b @r2,r0 \n" /* get data byte */
427 "shll8 r1 \n" /* old data to 2nd byte */
428 "extu.b r0,r0 \n" /* extend unsigned */
429 "or r1,r0 \n" /* combine old data */
430 "jmp @%[cnt] \n" /* jump into shift "path" */
431 "extu.b r0,r1 \n" /* store data for next round */
433 ".su_shift6: \n" /* shift right by 0..7 bits */
434 "shll2 r0 \n"
435 "bra .su_shift0 \n"
436 "shlr8 r0 \n"
437 ".su_shift4: \n"
438 "shlr2 r0 \n"
439 ".su_shift2: \n"
440 "bra .su_shift0 \n"
441 "shlr2 r0 \n"
442 ".su_shift7: \n"
443 "shlr2 r0 \n"
444 ".su_shift5: \n"
445 "shlr2 r0 \n"
446 ".su_shift3: \n"
447 "shlr2 r0 \n"
448 ".su_shift1: \n"
449 "shlr r0 \n"
450 ".su_shift0: \n"
452 "mov.b r0,@r2 \n" /* store data */
453 "add #1,r3 \n" /* current_row++ */
454 "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
455 "bt .su_iloop \n"
457 "add #1,%[addr] \n" /* start_address++ */
458 "add #1,r4 \n" /* x++ */
459 "cmp/hi r4,%[wide] \n" /* x < width ? */
460 "bt .su_cloop \n"
461 : /* outputs */
462 : /* inputs */
463 [addr]"r"(rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
464 [wide]"r"(LCD_FBWIDTH),
465 [rows]"r"(blocklen),
466 [cnt] "r"(bitcount)
467 : /* clobbers */
468 "r0", "r1", "r2", "r3", "r4"
470 #elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
471 asm (
472 "move.l %[wide],%%d3\n" /* columns = width */
474 ".su_cloop: \n" /* repeat for every column */
475 "move.l %[addr],%%a1\n" /* get start address */
476 "move.l %[rows],%%d2\n" /* rows = row_count */
477 "move.l %[bkg],%%d1 \n" /* fill with background */
479 ".su_iloop: \n" /* repeat for all rows */
480 "sub.l %[wide],%%a1\n" /* address -= width */
482 "lsl.l #8,%%d1 \n" /* old data to 2nd byte */
483 "move.b (%%a1),%%d1 \n" /* combine with new data byte */
484 "move.l %%d1,%%d0 \n" /* keep data for next round */
485 "lsr.l %[cnt],%%d0 \n" /* shift right */
486 "move.b %%d0,(%%a1) \n" /* store data */
488 "subq.l #1,%%d2 \n" /* rows-- */
489 "bne.b .su_iloop \n"
491 "addq.l #1,%[addr] \n" /* start_address++ */
492 "subq.l #1,%%d3 \n" /* columns-- */
493 "bne.b .su_cloop \n"
494 : /* outputs */
495 : /* inputs */
496 [wide]"r"(LCD_FBWIDTH),
497 [rows]"r"(blocklen),
498 [addr]"a"(rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
499 [cnt] "d"(bitcount),
500 [bkg] "d"(0x55 * (~rb->lcd_get_background() & 3))
501 : /* clobbers */
502 "a1", "d0", "d1", "d2", "d3"
504 #else /* C version */
505 int x, by;
506 unsigned char *addr = rb->lcd_framebuffer + blocklen * LCD_FBWIDTH;
507 #if LCD_DEPTH == 2
508 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
509 #else
510 const unsigned fill = 0;
511 #endif
513 for (x = 0; x < LCD_WIDTH; x++)
515 unsigned char *col_addr = addr++;
516 unsigned data = fill;
518 for (by = 0; by < blocklen; by++)
520 col_addr -= LCD_FBWIDTH;
521 data = (data << 8) | *col_addr;
522 *col_addr = data >> bitcount;
525 #endif /* CPU, LCD_DEPTH */
527 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
529 #if LCD_DEPTH == 2
530 int x, by;
531 fb_data *addr = rb->lcd_framebuffer + blocklen * LCD_FBWIDTH;
532 unsigned fill, mask;
534 fill = patterns[rb->lcd_get_background() & 3] << 8;
535 mask = (0xFFu >> bitcount) << bitcount;
536 mask |= mask << 8;
538 for (x = 0; x < LCD_WIDTH; x++)
540 fb_data *col_addr = addr++;
541 unsigned olddata = fill;
542 unsigned data;
544 for (by = 0; by < blocklen; by++)
546 col_addr -= LCD_FBWIDTH;
547 data = *col_addr;
548 *col_addr = (olddata ^ ((data ^ olddata) & mask)) >> bitcount;
549 olddata = data << 8;
552 #endif /* LCD_DEPTH == 2 */
554 #endif /* LCD_PIXELFORMAT */
556 oldmode = rb->lcd_get_drawmode();
557 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
558 rb->lcd_fillrect(0, LCD_HEIGHT - count, LCD_WIDTH, count);
559 rb->lcd_set_drawmode(oldmode);
562 /* Scroll up */
563 void xlcd_scroll_down(int count)
565 int bitcount, oldmode;
566 int blockcount, blocklen;
568 if ((unsigned) count >= LCD_HEIGHT)
570 rb->lcd_clear_display();
571 return;
574 #if (LCD_DEPTH == 1) \
575 || (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
576 blockcount = count >> 3;
577 bitcount = count & 7;
578 #elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
579 blockcount = count >> 2;
580 bitcount = 2 * (count & 3);
581 #endif
582 blocklen = LCD_FBHEIGHT - blockcount;
584 if (blockcount)
586 rb->memmove(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
587 rb->lcd_framebuffer,
588 blocklen * LCD_FBWIDTH * sizeof(fb_data));
590 if (bitcount)
592 #if LCD_PIXELFORMAT == VERTICAL_PACKING
594 #if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
595 asm (
596 "mov #0,r4 \n" /* x = 0 */
597 "mova .sd_shifttbl,r0 \n" /* calculate jump destination for */
598 "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
599 "bra .sd_cloop \n" /* skip table */
600 "add r0,%[cnt] \n"
602 ".align 2 \n"
603 ".sd_shifttbl: \n" /* shift jump offset table */
604 ".byte .sd_shift0 - .sd_shifttbl \n"
605 ".byte .sd_shift1 - .sd_shifttbl \n"
606 ".byte .sd_shift2 - .sd_shifttbl \n"
607 ".byte .sd_shift3 - .sd_shifttbl \n"
608 ".byte .sd_shift4 - .sd_shifttbl \n"
609 ".byte .sd_shift5 - .sd_shifttbl \n"
610 ".byte .sd_shift6 - .sd_shifttbl \n"
611 ".byte .sd_shift7 - .sd_shifttbl \n"
613 ".sd_cloop: \n" /* repeat for every column */
614 "mov %[addr],r2 \n" /* get start address */
615 "mov #0,r3 \n" /* current_row = 0 */
616 "mov #0,r1 \n" /* fill with zero */
618 ".sd_iloop: \n" /* repeat for all rows */
619 "shlr8 r1 \n" /* shift right to get residue */
620 "mov.b @r2,r0 \n" /* get data byte */
621 "jmp @%[cnt] \n" /* jump into shift "path" */
622 "extu.b r0,r0 \n" /* extend unsigned */
624 ".sd_shift6: \n" /* shift left by 0..7 bits */
625 "shll8 r0 \n"
626 "bra .sd_shift0 \n"
627 "shlr2 r0 \n"
628 ".sd_shift4: \n"
629 "shll2 r0 \n"
630 ".sd_shift2: \n"
631 "bra .sd_shift0 \n"
632 "shll2 r0 \n"
633 ".sd_shift7: \n"
634 "shll2 r0 \n"
635 ".sd_shift5: \n"
636 "shll2 r0 \n"
637 ".sd_shift3: \n"
638 "shll2 r0 \n"
639 ".sd_shift1: \n"
640 "shll r0 \n"
641 ".sd_shift0: \n"
643 "or r0,r1 \n" /* combine with last residue */
644 "mov.b r1,@r2 \n" /* store data */
645 "add %[wide],r2 \n" /* address += width */
646 "add #1,r3 \n" /* current_row++ */
647 "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
648 "bt .sd_iloop \n"
650 "add #1,%[addr] \n" /* start_address++ */
651 "add #1,r4 \n" /* x++ */
652 "cmp/hi r4,%[wide] \n" /* x < width ? */
653 "bt .sd_cloop \n"
654 : /* outputs */
655 : /* inputs */
656 [addr]"r"(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
657 [wide]"r"(LCD_WIDTH),
658 [rows]"r"(blocklen),
659 [cnt] "r"(bitcount)
660 : /* clobbers */
661 "r0", "r1", "r2", "r3", "r4"
663 #elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
664 asm (
665 "move.l %[wide],%%d3\n" /* columns = width */
667 ".sd_cloop: \n" /* repeat for every column */
668 "move.l %[addr],%%a1\n" /* get start address */
669 "move.l %[rows],%%d2\n" /* rows = row_count */
670 "move.l %[bkg],%%d1 \n" /* fill with background */
672 ".sd_iloop: \n" /* repeat for all rows */
673 "lsr.l #8,%%d1 \n" /* shift right to get residue */
674 "clr.l %%d0 \n"
675 "move.b (%%a1),%%d0 \n" /* get data byte */
676 "lsl.l %[cnt],%%d0 \n"
677 "or.l %%d0,%%d1 \n" /* combine with last residue */
678 "move.b %%d1,(%%a1) \n" /* store data */
680 "add.l %[wide],%%a1\n" /* address += width */
681 "subq.l #1,%%d2 \n" /* rows-- */
682 "bne.b .sd_iloop \n"
684 "lea.l (1,%[addr]),%[addr] \n" /* start_address++ */
685 "subq.l #1,%%d3 \n" /* columns-- */
686 "bne.b .sd_cloop \n"
687 : /* outputs */
688 : /* inputs */
689 [wide]"r"(LCD_WIDTH),
690 [rows]"r"(blocklen),
691 [addr]"a"(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
692 [cnt] "d"(bitcount),
693 [bkg] "d"((0x55 * (~rb->lcd_get_background() & 3)) << bitcount)
694 : /* clobbers */
695 "a1", "d0", "d1", "d2", "d3"
697 #else /* C version */
698 int x, by;
699 unsigned char *addr = rb->lcd_framebuffer + blockcount * LCD_FBWIDTH;
700 #if LCD_DEPTH == 2
701 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
702 #else
703 const unsigned fill = 0;
704 #endif
706 for (x = 0; x < LCD_WIDTH; x++)
708 unsigned char *col_addr = addr++;
709 unsigned data = fill;
711 for (by = 0; by < blocklen; by++)
713 data = (data >> 8) | (*col_addr << bitcount);
714 *col_addr = data;
715 col_addr += LCD_FBWIDTH;
718 #endif /* CPU, LCD_DEPTH */
720 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
722 #if LCD_DEPTH == 2
723 int x, by;
724 fb_data *addr = rb->lcd_framebuffer + blockcount * LCD_FBWIDTH;
725 unsigned fill, mask;
727 fill = patterns[rb->lcd_get_background() & 3] >> (8 - bitcount);
728 mask = (0xFFu >> bitcount) << bitcount;
729 mask |= mask << 8;
731 for (x = 0; x < LCD_WIDTH; x++)
733 fb_data *col_addr = addr++;
734 unsigned olddata = fill;
735 unsigned data;
737 for (by = 0; by < blocklen; by++)
739 data = *col_addr << bitcount;
740 *col_addr = olddata ^ ((data ^ olddata) & mask);
741 olddata = data >> 8;
742 col_addr += LCD_FBWIDTH;
745 #endif /* LCD_DEPTH == 2 */
747 #endif /* LCD_PIXELFORMAT */
749 oldmode = rb->lcd_get_drawmode();
750 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
751 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
752 rb->lcd_set_drawmode(oldmode);
755 #endif /* LCD_PIXELFORMAT, LCD_DEPTH */
756 #endif /* defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE */
758 #endif /* HAVE_LCD_BITMAP */