summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-2bit-horz.c
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2008-01-07 20:34:11 +0000
committerDave Chapman <dave@dchapman.com>2008-01-07 20:34:11 +0000
commit945c8a221ade41c462a93f8452320a806e5645b3 (patch)
tree2a17823e286e6252e60c44c7f4753d5c18ef5172 /firmware/drivers/lcd-2bit-horz.c
parent2a8f39820b49f116820356c2ca224f82f2106c21 (diff)
downloadrockbox-945c8a221ade41c462a93f8452320a806e5645b3.tar.gz
rockbox-945c8a221ade41c462a93f8452320a806e5645b3.zip
Add viewport capabilities to all the LCD drivers, and adapt scrolling code. This is the firmware/ part of FS#8385 - the changes to the WPS code still need more work and will be committed at a later date. NOTE: There are no user-visible changes with this commit - just the infrastructure.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16018 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/lcd-2bit-horz.c')
-rw-r--r--firmware/drivers/lcd-2bit-horz.c277
1 files changed, 192 insertions, 85 deletions
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c
index 32ebfa7f81..1ee0addba4 100644
--- a/firmware/drivers/lcd-2bit-horz.c
+++ b/firmware/drivers/lcd-2bit-horz.c
@@ -46,52 +46,92 @@ static const unsigned char pixmask[4] ICONST_ATTR = {
46static fb_data* lcd_backdrop = NULL; 46static fb_data* lcd_backdrop = NULL;
47static long lcd_backdrop_offset IDATA_ATTR = 0; 47static long lcd_backdrop_offset IDATA_ATTR = 0;
48 48
49static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */ 49static struct viewport default_vp =
50static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */ 50{
51static int drawmode = DRMODE_SOLID; 51 .x = 0,
52static int xmargin = 0; 52 .y = 0,
53static int ymargin = 0; 53 .width = LCD_WIDTH,
54static int curfont = FONT_SYSFIXED; 54 .height = LCD_HEIGHT,
55 .font = FONT_SYSFIXED,
56 .drawmode = DRMODE_SOLID,
57 .xmargin = 0,
58 .ymargin = 0,
59 .fg_pattern = LCD_DEFAULT_FG,
60 .bg_pattern = LCD_DEFAULT_BG
61};
62
63static struct viewport* current_vp IBSS_ATTR;
64static unsigned fg_pattern IBSS_ATTR;
65static unsigned bg_pattern IBSS_ATTR;
55 66
56/* LCD init */ 67/* LCD init */
57void lcd_init(void) 68void lcd_init(void)
58{ 69{
70 /* Initialise the viewport */
71 lcd_set_viewport(NULL);
72
59 lcd_clear_display(); 73 lcd_clear_display();
60 /* Call device specific init */ 74 /* Call device specific init */
61 lcd_init_device(); 75 lcd_init_device();
62 scroll_init(); 76 scroll_init();
63} 77}
64 78
79/*** Viewports ***/
80
81void lcd_set_viewport(struct viewport* vp)
82{
83 if (vp == NULL)
84 current_vp = &default_vp;
85 else
86 current_vp = vp;
87
88 fg_pattern = 0x55 * (~current_vp->fg_pattern & 3);
89 bg_pattern = 0x55 * (~current_vp->bg_pattern & 3);
90}
91
92void lcd_update_viewport(void)
93{
94 lcd_update_rect(current_vp->x, current_vp->y,
95 current_vp->width, current_vp->height);
96}
97
98void lcd_update_viewport_rect(int x, int y, int width, int height)
99{
100 lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height);
101}
102
65/*** parameter handling ***/ 103/*** parameter handling ***/
66 104
67void lcd_set_drawmode(int mode) 105void lcd_set_drawmode(int mode)
68{ 106{
69 drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); 107 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
70} 108}
71 109
72int lcd_get_drawmode(void) 110int lcd_get_drawmode(void)
73{ 111{
74 return drawmode; 112 return current_vp->drawmode;
75} 113}
76 114
77void lcd_set_foreground(unsigned brightness) 115void lcd_set_foreground(unsigned brightness)
78{ 116{
117 current_vp->fg_pattern = brightness;
79 fg_pattern = 0x55 * (~brightness & 3); 118 fg_pattern = 0x55 * (~brightness & 3);
80} 119}
81 120
82unsigned lcd_get_foreground(void) 121unsigned lcd_get_foreground(void)
83{ 122{
84 return ~fg_pattern & 3; 123 return current_vp->fg_pattern;
85} 124}
86 125
87void lcd_set_background(unsigned brightness) 126void lcd_set_background(unsigned brightness)
88{ 127{
128 current_vp->bg_pattern = brightness;
89 bg_pattern = 0x55 * (~brightness & 3); 129 bg_pattern = 0x55 * (~brightness & 3);
90} 130}
91 131
92unsigned lcd_get_background(void) 132unsigned lcd_get_background(void)
93{ 133{
94 return ~bg_pattern & 3; 134 return current_vp->bg_pattern;
95} 135}
96 136
97void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) 137void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness)
@@ -103,28 +143,38 @@ void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness)
103 143
104void lcd_setmargins(int x, int y) 144void lcd_setmargins(int x, int y)
105{ 145{
106 xmargin = x; 146 current_vp->xmargin = x;
107 ymargin = y; 147 current_vp->ymargin = y;
108} 148}
109 149
110int lcd_getxmargin(void) 150int lcd_getxmargin(void)
111{ 151{
112 return xmargin; 152 return current_vp->xmargin;
113} 153}
114 154
115int lcd_getymargin(void) 155int lcd_getymargin(void)
116{ 156{
117 return ymargin; 157 return current_vp->ymargin;
158}
159
160int lcd_getwidth(void)
161{
162 return current_vp->width;
163}
164
165int lcd_getheight(void)
166{
167 return current_vp->height;
118} 168}
119 169
120void lcd_setfont(int newfont) 170void lcd_setfont(int newfont)
121{ 171{
122 curfont = newfont; 172 current_vp->font = newfont;
123} 173}
124 174
125int lcd_getstringsize(const unsigned char *str, int *w, int *h) 175int lcd_getstringsize(const unsigned char *str, int *w, int *h)
126{ 176{
127 return font_getstringsize(str, w, h, curfont); 177 return font_getstringsize(str, w, h, current_vp->font);
128} 178}
129 179
130/*** low-level drawing functions ***/ 180/*** low-level drawing functions ***/
@@ -345,7 +395,7 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits)
345/* Clear the whole display */ 395/* Clear the whole display */
346void lcd_clear_display(void) 396void lcd_clear_display(void)
347{ 397{
348 if (drawmode & DRMODE_INVERSEVID) 398 if (current_vp->drawmode & DRMODE_INVERSEVID)
349 { 399 {
350 memset(lcd_framebuffer, fg_pattern, sizeof lcd_framebuffer); 400 memset(lcd_framebuffer, fg_pattern, sizeof lcd_framebuffer);
351 } 401 }
@@ -360,11 +410,37 @@ void lcd_clear_display(void)
360 lcd_scroll_info.lines = 0; 410 lcd_scroll_info.lines = 0;
361} 411}
362 412
413/* Clear the current viewport */
414void lcd_clear_viewport(void)
415{
416 int lastmode;
417
418 if (current_vp == &default_vp)
419 {
420 lcd_clear_display();
421 }
422 else
423 {
424 lastmode = current_vp->drawmode;
425
426 /* Invert the INVERSEVID bit and set basic mode to SOLID */
427 current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) |
428 DRMODE_SOLID;
429
430 lcd_fillrect(0, 0, current_vp->width, current_vp->height);
431
432 current_vp->drawmode = lastmode;
433
434 lcd_scroll_stop(current_vp);
435 }
436}
437
363/* Set a single pixel */ 438/* Set a single pixel */
364void lcd_drawpixel(int x, int y) 439void lcd_drawpixel(int x, int y)
365{ 440{
366 if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) 441 if (((unsigned)x < (unsigned)current_vp->width) &&
367 lcd_pixelfuncs[drawmode](x, y); 442 ((unsigned)y < (unsigned)current_vp->height))
443 lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y);
368} 444}
369 445
370/* Draw a line */ 446/* Draw a line */
@@ -376,7 +452,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
376 int d, dinc1, dinc2; 452 int d, dinc1, dinc2;
377 int x, xinc1, xinc2; 453 int x, xinc1, xinc2;
378 int y, yinc1, yinc2; 454 int y, yinc1, yinc2;
379 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; 455 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode];
380 456
381 deltax = abs(x2 - x1); 457 deltax = abs(x2 - x1);
382 deltay = abs(y2 - y1); 458 deltay = abs(y2 - y1);
@@ -420,8 +496,9 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
420 496
421 for (i = 0; i < numpixels; i++) 497 for (i = 0; i < numpixels; i++)
422 { 498 {
423 if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) 499 if (((unsigned)x < (unsigned)current_vp->width) &&
424 pfunc(x, y); 500 ((unsigned)y < (unsigned)current_vp->height))
501 pfunc(current_vp->x + x, current_vp->y + y);
425 502
426 if (d < 0) 503 if (d < 0)
427 { 504 {
@@ -455,16 +532,22 @@ void lcd_hline(int x1, int x2, int y)
455 } 532 }
456 533
457 /* nothing to draw? */ 534 /* nothing to draw? */
458 if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) 535 if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width)
536 || (x2 < 0))
459 return; 537 return;
460 538
461 /* clipping */ 539 /* clipping */
462 if (x1 < 0) 540 if (x1 < 0)
463 x1 = 0; 541 x1 = 0;
464 if (x2 >= LCD_WIDTH) 542 if (x2 >= current_vp->width)
465 x2 = LCD_WIDTH-1; 543 x2 = current_vp->width-1;
466 544
467 bfunc = lcd_blockfuncs[drawmode]; 545 /* adjust to viewport */
546 x1 += current_vp->x;
547 x2 += current_vp->x;
548 y += current_vp->y;
549
550 bfunc = lcd_blockfuncs[current_vp->drawmode];
468 dst = &lcd_framebuffer[y][x1>>2]; 551 dst = &lcd_framebuffer[y][x1>>2];
469 nx = x2 - (x1 & ~3); 552 nx = x2 - (x1 & ~3);
470 mask = 0xFFu >> (2 * (x1 & 3)); 553 mask = 0xFFu >> (2 * (x1 & 3));
@@ -496,16 +579,22 @@ void lcd_vline(int x, int y1, int y2)
496 } 579 }
497 580
498 /* nothing to draw? */ 581 /* nothing to draw? */
499 if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) 582 if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height)
583 || (y2 < 0))
500 return; 584 return;
501 585
502 /* clipping */ 586 /* clipping */
503 if (y1 < 0) 587 if (y1 < 0)
504 y1 = 0; 588 y1 = 0;
505 if (y2 >= LCD_HEIGHT) 589 if (y2 >= current_vp->height)
506 y2 = LCD_HEIGHT-1; 590 y2 = current_vp->height-1;
591
592 /* adjust for viewport */
593 y1 += current_vp->y;
594 y2 += current_vp->y;
595 x += current_vp->x;
507 596
508 bfunc = lcd_blockfuncs[drawmode]; 597 bfunc = lcd_blockfuncs[current_vp->drawmode];
509 dst = &lcd_framebuffer[y1][x>>2]; 598 dst = &lcd_framebuffer[y1][x>>2];
510 mask = pixmask[x & 3]; 599 mask = pixmask[x & 3];
511 600
@@ -542,7 +631,7 @@ void lcd_fillrect(int x, int y, int width, int height)
542 lcd_blockfunc_type *bfunc; 631 lcd_blockfunc_type *bfunc;
543 632
544 /* nothing to draw? */ 633 /* nothing to draw? */
545 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) 634 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || (y >= current_vp->height)
546 || (x + width <= 0) || (y + height <= 0)) 635 || (x + width <= 0) || (y + height <= 0))
547 return; 636 return;
548 637
@@ -557,12 +646,16 @@ void lcd_fillrect(int x, int y, int width, int height)
557 height += y; 646 height += y;
558 y = 0; 647 y = 0;
559 } 648 }
560 if (x + width > LCD_WIDTH) 649 if (x + width > current_vp->width)
561 width = LCD_WIDTH - x; 650 width = current_vp->width - x;
562 if (y + height > LCD_HEIGHT) 651 if (y + height > current_vp->height)
563 height = LCD_HEIGHT - y; 652 height = current_vp->height - y;
653
654 /* adjust for viewport */
655 x += current_vp->x;
656 y += current_vp->y;
564 657
565 bfunc = lcd_blockfuncs[drawmode]; 658 bfunc = lcd_blockfuncs[current_vp->drawmode];
566 dst = &lcd_framebuffer[y][x>>2]; 659 dst = &lcd_framebuffer[y][x>>2];
567 nx = width - 1 + (x & 3); 660 nx = width - 1 + (x & 3);
568 mask = 0xFFu >> (2 * (x & 3)); 661 mask = 0xFFu >> (2 * (x & 3));
@@ -616,8 +709,8 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
616 lcd_pixelfunc_type* bgfunc; 709 lcd_pixelfunc_type* bgfunc;
617 710
618 /* nothing to draw? */ 711 /* nothing to draw? */
619 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) 712 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
620 || (x + width <= 0) || (y + height <= 0)) 713 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
621 return; 714 return;
622 715
623 /* clipping */ 716 /* clipping */
@@ -633,17 +726,21 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
633 src_y -= y; 726 src_y -= y;
634 y = 0; 727 y = 0;
635 } 728 }
636 if (x + width > LCD_WIDTH) 729 if (x + width > current_vp->width)
637 width = LCD_WIDTH - x; 730 width = current_vp->width - x;
638 if (y + height > LCD_HEIGHT) 731 if (y + height > current_vp->height)
639 height = LCD_HEIGHT - y; 732 height = current_vp->height - y;
733
734 /* adjust for viewport */
735 x += current_vp->x;
736 y += current_vp->y;
640 737
641 src += stride * (src_y >> 3) + src_x; /* move starting point */ 738 src += stride * (src_y >> 3) + src_x; /* move starting point */
642 src_y &= 7; 739 src_y &= 7;
643 src_end = src + width; 740 src_end = src + width;
644 741
645 fgfunc = lcd_pixelfuncs[drawmode]; 742 fgfunc = lcd_pixelfuncs[current_vp->drawmode];
646 bgfunc = lcd_pixelfuncs[drawmode ^ DRMODE_INVERSEVID]; 743 bgfunc = lcd_pixelfuncs[current_vp->drawmode ^ DRMODE_INVERSEVID];
647 nx = x; 744 nx = x;
648 do 745 do
649 { 746 {
@@ -704,8 +801,8 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
704 unsigned mask, mask_right; 801 unsigned mask, mask_right;
705 802
706 /* nothing to draw? */ 803 /* nothing to draw? */
707 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) 804 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
708 || (x + width <= 0) || (y + height <= 0)) 805 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
709 return; 806 return;
710 807
711 /* clipping */ 808 /* clipping */
@@ -721,10 +818,14 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
721 src_y -= y; 818 src_y -= y;
722 y = 0; 819 y = 0;
723 } 820 }
724 if (x + width > LCD_WIDTH) 821 if (x + width > current_vp->width)
725 width = LCD_WIDTH - x; 822 width = current_vp->width - x;
726 if (y + height > LCD_HEIGHT) 823 if (y + height > current_vp->height)
727 height = LCD_HEIGHT - y; 824 height = current_vp->height - y;
825
826 /* adjust for viewport */
827 x += current_vp->x;
828 y += current_vp->y;
728 829
729 stride = (stride + 3) >> 2; /* convert to no. of bytes */ 830 stride = (stride + 3) >> 2; /* convert to no. of bytes */
730 831
@@ -781,11 +882,11 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
781{ 882{
782 unsigned short ch; 883 unsigned short ch;
783 unsigned short *ucs; 884 unsigned short *ucs;
784 struct font* pf = font_get(curfont); 885 struct font* pf = font_get(current_vp->font);
785 886
786 ucs = bidi_l2v(str, 1); 887 ucs = bidi_l2v(str, 1);
787 888
788 while ((ch = *ucs++) != 0 && x < LCD_WIDTH) 889 while ((ch = *ucs++) != 0 && x < current_vp->width)
789 { 890 {
790 int width; 891 int width;
791 const unsigned char *bits; 892 const unsigned char *bits;
@@ -839,24 +940,24 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str,
839 int style, int offset) 940 int style, int offset)
840{ 941{
841 int xpos,ypos,w,h,xrect; 942 int xpos,ypos,w,h,xrect;
842 int lastmode = drawmode; 943 int lastmode = current_vp->drawmode;
843 944
844 /* make sure scrolling is turned off on the line we are updating */ 945 /* make sure scrolling is turned off on the line we are updating */
845 lcd_scroll_info.lines &= ~(1 << y); 946 lcd_scroll_stop_line(current_vp, y);
846 947
847 if(!str || !str[0]) 948 if(!str || !str[0])
848 return; 949 return;
849 950
850 lcd_getstringsize(str, &w, &h); 951 lcd_getstringsize(str, &w, &h);
851 xpos = xmargin + x*w / utf8length((char *)str); 952 xpos = current_vp->xmargin + x*w / utf8length((char *)str);
852 ypos = ymargin + y*h; 953 ypos = current_vp->ymargin + y*h;
853 drawmode = (style & STYLE_INVERT) ? 954 current_vp->drawmode = (style & STYLE_INVERT) ?
854 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 955 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
855 lcd_putsxyofs(xpos, ypos, offset, str); 956 lcd_putsxyofs(xpos, ypos, offset, str);
856 drawmode ^= DRMODE_INVERSEVID; 957 current_vp->drawmode ^= DRMODE_INVERSEVID;
857 xrect = xpos + MAX(w - offset, 0); 958 xrect = xpos + MAX(w - offset, 0);
858 lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h); 959 lcd_fillrect(xrect, ypos, current_vp->width - xrect, h);
859 drawmode = lastmode; 960 current_vp->drawmode = lastmode;
860} 961}
861 962
862/*** scrolling ***/ 963/*** scrolling ***/
@@ -881,9 +982,15 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
881 struct scrollinfo* s; 982 struct scrollinfo* s;
882 int w, h; 983 int w, h;
883 984
884 if(y>=LCD_SCROLLABLE_LINES) return; 985 if ((unsigned)y >= (unsigned)current_vp->height)
986 return;
987
988 /* remove any previously scrolling line at the same location */
989 lcd_scroll_stop_line(current_vp, y);
885 990
886 s = &lcd_scroll_info.scroll[y]; 991 if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return;
992
993 s = &lcd_scroll_info.scroll[lcd_scroll_info.lines];
887 994
888 s->start_tick = current_tick + lcd_scroll_info.delay; 995 s->start_tick = current_tick + lcd_scroll_info.delay;
889 s->style = style; 996 s->style = style;
@@ -895,7 +1002,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
895 1002
896 lcd_getstringsize(string, &w, &h); 1003 lcd_getstringsize(string, &w, &h);
897 1004
898 if (LCD_WIDTH - x * 8 - xmargin < w) { 1005 if (current_vp->width - x * 8 - current_vp->xmargin < w) {
899 /* prepare scroll line */ 1006 /* prepare scroll line */
900 char *end; 1007 char *end;
901 1008
@@ -908,7 +1015,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
908 /* scroll bidirectional or forward only depending on the string 1015 /* scroll bidirectional or forward only depending on the string
909 width */ 1016 width */
910 if ( lcd_scroll_info.bidir_limit ) { 1017 if ( lcd_scroll_info.bidir_limit ) {
911 s->bidir = s->width < (LCD_WIDTH - xmargin) * 1018 s->bidir = s->width < (current_vp->width - current_vp->xmargin) *
912 (100 + lcd_scroll_info.bidir_limit) / 100; 1019 (100 + lcd_scroll_info.bidir_limit) / 100;
913 } 1020 }
914 else 1021 else
@@ -921,17 +1028,16 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
921 } 1028 }
922 1029
923 end = strchr(s->line, '\0'); 1030 end = strchr(s->line, '\0');
924 strncpy(end, (char *)string, LCD_WIDTH/2); 1031 strncpy(end, (char *)string, current_vp->width/2);
925 1032
1033 s->vp = current_vp;
1034 s->y = y;
926 s->len = utf8length((char *)string); 1035 s->len = utf8length((char *)string);
927 s->offset = offset; 1036 s->offset = offset;
928 s->startx = xmargin + x * s->width / s->len;; 1037 s->startx = current_vp->xmargin + x * s->width / s->len;;
929 s->backward = false; 1038 s->backward = false;
930 lcd_scroll_info.lines |= (1<<y); 1039 lcd_scroll_info.lines++;
931 } 1040 }
932 else
933 /* force a bit switch-off since it doesn't scroll */
934 lcd_scroll_info.lines &= ~(1<<y);
935} 1041}
936 1042
937void lcd_scroll_fn(void) 1043void lcd_scroll_fn(void)
@@ -941,26 +1047,25 @@ void lcd_scroll_fn(void)
941 int index; 1047 int index;
942 int xpos, ypos; 1048 int xpos, ypos;
943 int lastmode; 1049 int lastmode;
1050 struct viewport* old_vp = current_vp;
944 1051
945 for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) { 1052 for ( index = 0; index < lcd_scroll_info.lines; index++ ) {
946 /* really scroll? */
947 if ((lcd_scroll_info.lines & (1 << index)) == 0)
948 continue;
949
950 s = &lcd_scroll_info.scroll[index]; 1053 s = &lcd_scroll_info.scroll[index];
951 1054
952 /* check pause */ 1055 /* check pause */
953 if (TIME_BEFORE(current_tick, s->start_tick)) 1056 if (TIME_BEFORE(current_tick, s->start_tick))
954 continue; 1057 continue;
955 1058
1059 lcd_set_viewport(s->vp);
1060
956 if (s->backward) 1061 if (s->backward)
957 s->offset -= lcd_scroll_info.step; 1062 s->offset -= lcd_scroll_info.step;
958 else 1063 else
959 s->offset += lcd_scroll_info.step; 1064 s->offset += lcd_scroll_info.step;
960 1065
961 pf = font_get(curfont); 1066 pf = font_get(current_vp->font);
962 xpos = s->startx; 1067 xpos = s->startx;
963 ypos = ymargin + index * pf->height; 1068 ypos = current_vp->ymargin + s->y * pf->height;
964 1069
965 if (s->bidir) { /* scroll bidirectional */ 1070 if (s->bidir) { /* scroll bidirectional */
966 if (s->offset <= 0) { 1071 if (s->offset <= 0) {
@@ -969,9 +1074,9 @@ void lcd_scroll_fn(void)
969 s->backward = false; 1074 s->backward = false;
970 s->start_tick = current_tick + lcd_scroll_info.delay * 2; 1075 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
971 } 1076 }
972 if (s->offset >= s->width - (LCD_WIDTH - xpos)) { 1077 if (s->offset >= s->width - (current_vp->width - xpos)) {
973 /* at end of line */ 1078 /* at end of line */
974 s->offset = s->width - (LCD_WIDTH - xpos); 1079 s->offset = s->width - (current_vp->width - xpos);
975 s->backward = true; 1080 s->backward = true;
976 s->start_tick = current_tick + lcd_scroll_info.delay * 2; 1081 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
977 } 1082 }
@@ -982,11 +1087,13 @@ void lcd_scroll_fn(void)
982 s->offset %= s->width; 1087 s->offset %= s->width;
983 } 1088 }
984 1089
985 lastmode = drawmode; 1090 lastmode = current_vp->drawmode;
986 drawmode = (s->style&STYLE_INVERT) ? 1091 current_vp->drawmode = (s->style&STYLE_INVERT) ?
987 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 1092 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
988 lcd_putsxyofs(xpos, ypos, s->offset, s->line); 1093 lcd_putsxyofs(xpos, ypos, s->offset, s->line);
989 drawmode = lastmode; 1094 current_vp->drawmode = lastmode;
990 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); 1095 lcd_update_viewport_rect(xpos, ypos, current_vp->width - xpos, pf->height);
991 } 1096 }
1097
1098 lcd_set_viewport(old_vp);
992} 1099}