diff options
author | Jens Arnold <amiconn@rockbox.org> | 2004-05-21 20:48:35 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2004-05-21 20:48:35 +0000 |
commit | 9ca74798b6a923377b5d4745121ce51228eeee7f (patch) | |
tree | 9ae04ebec22334937a21f5d50aa8b8f93f952b2f /apps/plugins/lib | |
parent | a4f39a63614b711df0890a81b69012ab37938736 (diff) | |
download | rockbox-9ca74798b6a923377b5d4745121ce51228eeee7f.tar.gz rockbox-9ca74798b6a923377b5d4745121ce51228eeee7f.zip |
Fix: scrolling left/right with even pixel counts caused an address error if the buffer width was odd. Some more tweaks and cleanups.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4681 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/lib')
-rw-r--r-- | apps/plugins/lib/gray.c | 157 |
1 files changed, 83 insertions, 74 deletions
diff --git a/apps/plugins/lib/gray.c b/apps/plugins/lib/gray.c index cf7063aeeb..ed95a39dea 100644 --- a/apps/plugins/lib/gray.c +++ b/apps/plugins/lib/gray.c | |||
@@ -77,7 +77,7 @@ static void gray_timer_isr(void) | |||
77 | int x1 = MAX(graybuf->x, 0); | 77 | int x1 = MAX(graybuf->x, 0); |
78 | int x2 = MIN(graybuf->x + graybuf->width, LCD_WIDTH); | 78 | int x2 = MIN(graybuf->x + graybuf->width, LCD_WIDTH); |
79 | int y1 = MAX(graybuf->by << 3, 0); | 79 | int y1 = MAX(graybuf->by << 3, 0); |
80 | int y2 = MIN((graybuf->by + graybuf->bheight) << 3, LCD_HEIGHT); | 80 | int y2 = MIN((graybuf->by << 3) + graybuf->height, LCD_HEIGHT); |
81 | 81 | ||
82 | if (y1 > 0) /* refresh part above overlay, full width */ | 82 | if (y1 > 0) /* refresh part above overlay, full width */ |
83 | rb->lcd_update_rect(0, 0, LCD_WIDTH, y1); | 83 | rb->lcd_update_rect(0, 0, LCD_WIDTH, y1); |
@@ -108,7 +108,7 @@ static void graypixel(int x, int y, unsigned long pattern) | |||
108 | * It delivers max. 16 pseudo-random bits in each iteration. */ | 108 | * It delivers max. 16 pseudo-random bits in each iteration. */ |
109 | 109 | ||
110 | /* simple but fast pseudo-random generator */ | 110 | /* simple but fast pseudo-random generator */ |
111 | asm( | 111 | asm ( |
112 | "mov #75,r1 \n" | 112 | "mov #75,r1 \n" |
113 | "mulu %1,r1 \n" /* multiply by 75 */ | 113 | "mulu %1,r1 \n" /* multiply by 75 */ |
114 | "sts macl,%1 \n" /* get result */ | 114 | "sts macl,%1 \n" /* get result */ |
@@ -126,7 +126,7 @@ static void graypixel(int x, int y, unsigned long pattern) | |||
126 | ); | 126 | ); |
127 | 127 | ||
128 | /* precalculate mask and byte address in first bitplane */ | 128 | /* precalculate mask and byte address in first bitplane */ |
129 | asm( | 129 | asm ( |
130 | "mov %3,%0 \n" /* take y as base for address offset */ | 130 | "mov %3,%0 \n" /* take y as base for address offset */ |
131 | "shlr2 %0 \n" /* shift right by 3 (= divide by 8) */ | 131 | "shlr2 %0 \n" /* shift right by 3 (= divide by 8) */ |
132 | "shlr %0 \n" | 132 | "shlr %0 \n" |
@@ -164,7 +164,7 @@ static void graypixel(int x, int y, unsigned long pattern) | |||
164 | ); | 164 | ); |
165 | 165 | ||
166 | /* the hard part: set bits in all bitplanes according to pattern */ | 166 | /* the hard part: set bits in all bitplanes according to pattern */ |
167 | asm( | 167 | asm volatile ( |
168 | "cmp/hs %1,%5 \n" /* random >= depth ? */ | 168 | "cmp/hs %1,%5 \n" /* random >= depth ? */ |
169 | "bf .p_ntrim \n" | 169 | "bf .p_ntrim \n" |
170 | "sub %1,%5 \n" /* yes: random -= depth */ | 170 | "sub %1,%5 \n" /* yes: random -= depth */ |
@@ -240,7 +240,7 @@ static void grayblock(int x, int by, unsigned char* src, int stride) | |||
240 | /* precalculate the bit patterns with random shifts (same RNG as graypixel, | 240 | /* precalculate the bit patterns with random shifts (same RNG as graypixel, |
241 | * see there for an explanation) for all 8 pixels and put them on an | 241 | * see there for an explanation) for all 8 pixels and put them on an |
242 | * extra stack */ | 242 | * extra stack */ |
243 | asm( | 243 | asm ( |
244 | "mova .gb_reload,r0 \n" /* set default loopback address */ | 244 | "mova .gb_reload,r0 \n" /* set default loopback address */ |
245 | "tst %3,%3 \n" /* stride == 0 ? */ | 245 | "tst %3,%3 \n" /* stride == 0 ? */ |
246 | "bf .gb_needreload \n" /* no: keep that address */ | 246 | "bf .gb_needreload \n" /* no: keep that address */ |
@@ -323,7 +323,7 @@ static void grayblock(int x, int by, unsigned char* src, int stride) | |||
323 | 323 | ||
324 | /* set the bits for all 8 pixels in all bytes according to the | 324 | /* set the bits for all 8 pixels in all bytes according to the |
325 | * precalculated patterns on the pattern stack */ | 325 | * precalculated patterns on the pattern stack */ |
326 | asm ( | 326 | asm volatile ( |
327 | "mov.l @%3+,r1 \n" /* pop all 8 patterns */ | 327 | "mov.l @%3+,r1 \n" /* pop all 8 patterns */ |
328 | "mov.l @%3+,r2 \n" | 328 | "mov.l @%3+,r2 \n" |
329 | "mov.l @%3+,r3 \n" | 329 | "mov.l @%3+,r3 \n" |
@@ -368,7 +368,7 @@ static void grayblock(int x, int by, unsigned char* src, int stride) | |||
368 | /* Invert the bits for 1-8 pixels within the buffer */ | 368 | /* Invert the bits for 1-8 pixels within the buffer */ |
369 | static void grayinvertmasked(int x, int by, unsigned char mask) | 369 | static void grayinvertmasked(int x, int by, unsigned char mask) |
370 | { | 370 | { |
371 | asm( | 371 | asm volatile ( |
372 | "mulu %4,%5 \n" /* width * by (offset of row) */ | 372 | "mulu %4,%5 \n" /* width * by (offset of row) */ |
373 | "mov #0,r1 \n" /* current_plane = 0 */ | 373 | "mov #0,r1 \n" /* current_plane = 0 */ |
374 | "sts macl,r2 \n" /* get mulu result */ | 374 | "sts macl,r2 \n" /* get mulu result */ |
@@ -473,7 +473,7 @@ int gray_init_buffer(unsigned char *gbuf, int gbuf_size, int width, | |||
473 | graybuf->data = (unsigned char *) (graybuf->bitpattern + depth + 1); | 473 | graybuf->data = (unsigned char *) (graybuf->bitpattern + depth + 1); |
474 | graybuf->curfont = FONT_SYSFIXED; | 474 | graybuf->curfont = FONT_SYSFIXED; |
475 | 475 | ||
476 | i = depth; | 476 | i = depth - 1; |
477 | j = 8; | 477 | j = 8; |
478 | while (i != 0) | 478 | while (i != 0) |
479 | { | 479 | { |
@@ -660,36 +660,39 @@ void gray_scroll_left(int count, bool black_border) | |||
660 | ptr = graybuf->data + MULU16(graybuf->width, by); | 660 | ptr = graybuf->data + MULU16(graybuf->width, by); |
661 | for (d = 0; d < graybuf->depth; d++) | 661 | for (d = 0; d < graybuf->depth; d++) |
662 | { | 662 | { |
663 | if (count & 1) /* odd count: scroll byte-wise */ | 663 | asm volatile ( |
664 | asm volatile ( | 664 | "mov %0,r1 \n" /* check if both source... */ |
665 | ".sl_loop1: \n" | 665 | "or %2,r1 \n" /* ...and offset are even */ |
666 | "mov.b @%0+,r1 \n" | 666 | "shlr r1 \n" /* -> lsb = 0 */ |
667 | "mov.b r1,@(%2,%0) \n" | 667 | "bf .sl_start2 \n" /* -> copy word-wise */ |
668 | "cmp/hi %0,%1 \n" | 668 | |
669 | "bt .sl_loop1 \n" | 669 | "add #-1,%2 \n" /* copy byte-wise */ |
670 | : /* outputs */ | 670 | ".sl_loop1: \n" |
671 | : /* inputs */ | 671 | "mov.b @%0+,r1 \n" |
672 | /* %0 */ "r"(ptr + count), | 672 | "mov.b r1,@(%2,%0) \n" |
673 | /* %1 */ "r"(ptr + graybuf->width), | 673 | "cmp/hi %0,%1 \n" |
674 | /* %2 */ "z"(-count - 1) | 674 | "bt .sl_loop1 \n" |
675 | : /* clobbers */ | 675 | |
676 | "r1" | 676 | "bra .sl_end \n" |
677 | ); | 677 | "nop \n" |
678 | else /* even count: scroll word-wise */ | 678 | |
679 | asm volatile ( | 679 | ".sl_start2: \n" /* copy word-wise */ |
680 | ".sl_loop2: \n" | 680 | "add #-2,%2 \n" |
681 | "mov.w @%0+,r1 \n" | 681 | ".sl_loop2: \n" |
682 | "mov.w r1,@(%2,%0) \n" | 682 | "mov.w @%0+,r1 \n" |
683 | "cmp/hi %0,%1 \n" | 683 | "mov.w r1,@(%2,%0) \n" |
684 | "bt .sl_loop2 \n" | 684 | "cmp/hi %0,%1 \n" |
685 | : /* outputs */ | 685 | "bt .sl_loop2 \n" |
686 | : /* inputs */ | 686 | |
687 | /* %0 */ "r"(ptr + count), | 687 | ".sl_end: \n" |
688 | /* %1 */ "r"(ptr + graybuf->width), | 688 | : /* outputs */ |
689 | /* %2 */ "z"(-count - 2) | 689 | : /* inputs */ |
690 | : /* clobbers */ | 690 | /* %0 */ "r"(ptr + count), |
691 | "r1" | 691 | /* %1 */ "r"(ptr + graybuf->width), |
692 | ); | 692 | /* %2 */ "z"(-count) |
693 | : /* clobbers */ | ||
694 | "r1" | ||
695 | ); | ||
693 | 696 | ||
694 | rb->memset(ptr + graybuf->width - count, filler, count); | 697 | rb->memset(ptr + graybuf->width - count, filler, count); |
695 | ptr += graybuf->plane_size; | 698 | ptr += graybuf->plane_size; |
@@ -725,36 +728,39 @@ void gray_scroll_right(int count, bool black_border) | |||
725 | ptr = graybuf->data + MULU16(graybuf->width, by); | 728 | ptr = graybuf->data + MULU16(graybuf->width, by); |
726 | for (d = 0; d < graybuf->depth; d++) | 729 | for (d = 0; d < graybuf->depth; d++) |
727 | { | 730 | { |
728 | if (count & 1) /* odd count: scroll byte-wise */ | 731 | asm volatile ( |
729 | asm volatile ( | 732 | "mov %0,r1 \n" /* check if both source... */ |
730 | ".sr_loop1: \n" | 733 | "or %2,r1 \n" /* ...and offset are even */ |
731 | "mov.b @(%2,%0),r1 \n" | 734 | "shlr r1 \n" /* -> lsb = 0 */ |
732 | "mov.b r1,@-%0 \n" | 735 | "bf .sr_start2 \n" /* -> copy word-wise */ |
733 | "cmp/hi %1,%0 \n" | 736 | |
734 | "bt .sr_loop1 \n" | 737 | "add #-1,%2 \n" /* copy byte-wise */ |
735 | : /* outputs */ | 738 | ".sr_loop1: \n" |
736 | : /* inputs */ | 739 | "mov.b @(%2,%0),r1 \n" |
737 | /* %0 */ "r"(ptr + graybuf->width), | 740 | "mov.b r1,@-%0 \n" |
738 | /* %1 */ "r"(ptr + count), | 741 | "cmp/hi %1,%0 \n" |
739 | /* %2 */ "z"(-count - 1) | 742 | "bt .sr_loop1 \n" |
740 | : /* clobbers */ | 743 | |
741 | "r1" | 744 | "bra .sr_end \n" |
742 | ); | 745 | "nop \n" |
743 | else /* even count: scroll word-wise */ | 746 | |
744 | asm volatile ( | 747 | ".sr_start2: \n" /* copy word-wise */ |
745 | ".sr_loop2: \n" | 748 | "add #-2,%2 \n" |
746 | "mov.w @(%2,%0),r1 \n" | 749 | ".sr_loop2: \n" |
747 | "mov.w r1,@-%0 \n" | 750 | "mov.w @(%2,%0),r1 \n" |
748 | "cmp/hi %1,%0 \n" | 751 | "mov.w r1,@-%0 \n" |
749 | "bt .sr_loop2 \n" | 752 | "cmp/hi %1,%0 \n" |
750 | : /* outputs */ | 753 | "bt .sr_loop2 \n" |
751 | : /* inputs */ | 754 | |
752 | /* %0 */ "r"(ptr + graybuf->width), | 755 | ".sr_end: \n" |
753 | /* %1 */ "r"(ptr + count), | 756 | : /* outputs */ |
754 | /* %2 */ "z"(-count - 2) | 757 | : /* inputs */ |
755 | : /* clobbers */ | 758 | /* %0 */ "r"(ptr + graybuf->width), |
756 | "r1" | 759 | /* %1 */ "r"(ptr + count), |
757 | ); | 760 | /* %2 */ "z"(-count) |
761 | : /* clobbers */ | ||
762 | "r1" | ||
763 | ); | ||
758 | 764 | ||
759 | rb->memset(ptr, filler, count); | 765 | rb->memset(ptr, filler, count); |
760 | ptr += graybuf->plane_size; | 766 | ptr += graybuf->plane_size; |
@@ -864,7 +870,7 @@ void gray_scroll_up(int count, bool black_border) | |||
864 | filler = 0; | 870 | filler = 0; |
865 | 871 | ||
866 | /* scroll column by column to minimize flicker */ | 872 | /* scroll column by column to minimize flicker */ |
867 | asm( | 873 | asm volatile ( |
868 | "mov #0,r6 \n" /* x = 0 */ | 874 | "mov #0,r6 \n" /* x = 0 */ |
869 | "mova .su_shifttbl,r0 \n" /* calculate jump destination for */ | 875 | "mova .su_shifttbl,r0 \n" /* calculate jump destination for */ |
870 | "mov.b @(r0,%6),%6 \n" /* shift amount from table */ | 876 | "mov.b @(r0,%6),%6 \n" /* shift amount from table */ |
@@ -967,7 +973,7 @@ void gray_scroll_down(int count, bool black_border) | |||
967 | filler = 0; | 973 | filler = 0; |
968 | 974 | ||
969 | /* scroll column by column to minimize flicker */ | 975 | /* scroll column by column to minimize flicker */ |
970 | asm( | 976 | asm volatile ( |
971 | "mov #0,r6 \n" /* x = 0 */ | 977 | "mov #0,r6 \n" /* x = 0 */ |
972 | "mova .sd_shifttbl,r0 \n" /* calculate jump destination for */ | 978 | "mova .sd_shifttbl,r0 \n" /* calculate jump destination for */ |
973 | "mov.b @(r0,%6),%6 \n" /* shift amount from table */ | 979 | "mov.b @(r0,%6),%6 \n" /* shift amount from table */ |
@@ -1431,7 +1437,7 @@ void gray_invertrect(int x1, int y1, int x2, int y2) | |||
1431 | void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny, | 1437 | void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny, |
1432 | int stride) | 1438 | int stride) |
1433 | { | 1439 | { |
1434 | int xi, yi; | 1440 | int xi, yi, byte; |
1435 | unsigned char *row; | 1441 | unsigned char *row; |
1436 | 1442 | ||
1437 | if (graybuf == NULL | 1443 | if (graybuf == NULL |
@@ -1464,7 +1470,9 @@ void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny, | |||
1464 | { | 1470 | { |
1465 | for (xi = x; xi < x + nx; xi++) | 1471 | for (xi = x; xi < x + nx; xi++) |
1466 | { | 1472 | { |
1467 | graypixel(xi, yi, graybuf->bitpattern[MULU16(*row++, | 1473 | byte = *row++; |
1474 | /* separated to force GCC to use 16bit multiplication below */ | ||
1475 | graypixel(xi, yi, graybuf->bitpattern[MULU16(byte, | ||
1468 | graybuf->depth + 1) >> 8]); | 1476 | graybuf->depth + 1) >> 8]); |
1469 | } | 1477 | } |
1470 | yi++; | 1478 | yi++; |
@@ -1609,8 +1617,9 @@ void gray_putsxy(int x, int y, unsigned char *str, bool draw_bg, | |||
1609 | 1617 | ||
1610 | /* get proportional width and glyph bits */ | 1618 | /* get proportional width and glyph bits */ |
1611 | width = pf->width ? pf->width[ch] : pf->maxwidth; | 1619 | width = pf->width ? pf->width[ch] : pf->maxwidth; |
1612 | bits = pf->bits + (pf->offset ? pf->offset[ch] : (pf->height * ch)); | 1620 | bits = pf->bits + (pf->offset ? pf->offset[ch] |
1613 | 1621 | : MULU16(pf->height, ch)); | |
1622 | |||
1614 | gray_drawbitmap((unsigned char*) bits, x, y, width, pf->height, | 1623 | gray_drawbitmap((unsigned char*) bits, x, y, width, pf->height, |
1615 | width, draw_bg, fg_brightness, bg_brightness); | 1624 | width, draw_bg, fg_brightness, bg_brightness); |
1616 | x += width; | 1625 | x += width; |