diff options
Diffstat (limited to 'apps/plugins/lib')
-rw-r--r-- | apps/plugins/lib/SOURCES | 4 | ||||
-rw-r--r-- | apps/plugins/lib/grey.h | 166 | ||||
-rw-r--r-- | apps/plugins/lib/grey_core.c | 767 | ||||
-rw-r--r-- | apps/plugins/lib/grey_draw.c | 681 | ||||
-rw-r--r-- | apps/plugins/lib/grey_parm.c | 116 | ||||
-rw-r--r-- | apps/plugins/lib/grey_scroll.c | 358 |
6 files changed, 2092 insertions, 0 deletions
diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES index f6711840ee..5433f7e1d7 100644 --- a/apps/plugins/lib/SOURCES +++ b/apps/plugins/lib/SOURCES | |||
@@ -8,6 +8,10 @@ gray_core.c | |||
8 | gray_draw.c | 8 | gray_draw.c |
9 | gray_parm.c | 9 | gray_parm.c |
10 | gray_scroll.c | 10 | gray_scroll.c |
11 | grey_core.c | ||
12 | grey_draw.c | ||
13 | grey_parm.c | ||
14 | grey_scroll.c | ||
11 | #endif | 15 | #endif |
12 | highscore.c | 16 | highscore.c |
13 | #ifndef SIMULATOR | 17 | #ifndef SIMULATOR |
diff --git a/apps/plugins/lib/grey.h b/apps/plugins/lib/grey.h new file mode 100644 index 0000000000..136794bd26 --- /dev/null +++ b/apps/plugins/lib/grey.h | |||
@@ -0,0 +1,166 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * New greyscale framework | ||
11 | * | ||
12 | * This is a generic framework to display 129 shades of grey on low-depth | ||
13 | * bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. | ||
14 | * | ||
15 | * Copyright (C) 2008 Jens Arnold | ||
16 | * | ||
17 | * All files in this archive are subject to the GNU General Public License. | ||
18 | * See the file COPYING in the source tree root for full license agreement. | ||
19 | * | ||
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
21 | * KIND, either express or implied. | ||
22 | * | ||
23 | ****************************************************************************/ | ||
24 | |||
25 | #ifndef __GREY_H__ | ||
26 | #define __GREY_H__ | ||
27 | |||
28 | #include "plugin.h" | ||
29 | |||
30 | #if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) | ||
31 | |||
32 | #define GREY_BRIGHTNESS(y) (y) | ||
33 | |||
34 | #define GREY_BLACK GREY_BRIGHTNESS(0) | ||
35 | #define GREY_DARKGRAY GREY_BRIGHTNESS(85) | ||
36 | #define GREY_LIGHTGRAY GREY_BRIGHTNESS(170) | ||
37 | #define GREY_WHITE GREY_BRIGHTNESS(255) | ||
38 | |||
39 | /* Library initialisation and release */ | ||
40 | bool grey_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size, | ||
41 | bool buffered, int width, int height, long *buf_taken); | ||
42 | void grey_release(void); | ||
43 | |||
44 | /* Special functions */ | ||
45 | void grey_show(bool enable); | ||
46 | void grey_deferred_lcd_update(void); | ||
47 | |||
48 | /* Update functions */ | ||
49 | void grey_update(void); | ||
50 | void grey_update_rect(int x, int y, int width, int height); | ||
51 | |||
52 | /* Parameter handling */ | ||
53 | void grey_set_position(int x, int y); | ||
54 | void grey_set_drawmode(int mode); | ||
55 | int grey_get_drawmode(void); | ||
56 | void grey_set_foreground(unsigned brightness); | ||
57 | unsigned grey_get_foreground(void); | ||
58 | void grey_set_background(unsigned brightness); | ||
59 | unsigned grey_get_background(void); | ||
60 | void grey_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness); | ||
61 | void grey_setfont(int newfont); | ||
62 | int grey_getstringsize(const unsigned char *str, int *w, int *h); | ||
63 | |||
64 | /* Whole display */ | ||
65 | void grey_clear_display(void); | ||
66 | void grey_ub_clear_display(void); | ||
67 | |||
68 | /* Pixel */ | ||
69 | void grey_drawpixel(int x, int y); | ||
70 | |||
71 | /* Lines */ | ||
72 | void grey_drawline(int x1, int y1, int x2, int y2); | ||
73 | void grey_hline(int x1, int x2, int y); | ||
74 | void grey_vline(int x, int y1, int y2); | ||
75 | void grey_drawrect(int x, int y, int nx, int ny); | ||
76 | |||
77 | /* Filled primitives */ | ||
78 | void grey_fillrect(int x, int y, int nx, int ny); | ||
79 | void grey_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3); | ||
80 | |||
81 | /* Bitmaps */ | ||
82 | void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | ||
83 | int stride, int x, int y, int width, int height); | ||
84 | void grey_mono_bitmap(const unsigned char *src, int x, int y, int width, | ||
85 | int height); | ||
86 | void grey_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, | ||
87 | int stride, int x, int y, int width, int height); | ||
88 | void grey_gray_bitmap(const unsigned char *src, int x, int y, int width, | ||
89 | int height); | ||
90 | void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, | ||
91 | int stride, int x, int y, int width, int height); | ||
92 | void grey_ub_gray_bitmap(const unsigned char *src, int x, int y, int width, | ||
93 | int height); | ||
94 | |||
95 | /* Text */ | ||
96 | void grey_putsxyofs(int x, int y, int ofs, const unsigned char *str); | ||
97 | void grey_putsxy(int x, int y, const unsigned char *str); | ||
98 | |||
99 | /* Scrolling */ | ||
100 | void grey_scroll_left(int count); | ||
101 | void grey_scroll_right(int count); | ||
102 | void grey_scroll_up(int count); | ||
103 | void grey_scroll_down(int count); | ||
104 | void grey_ub_scroll_left(int count); | ||
105 | void grey_ub_scroll_right(int count); | ||
106 | void grey_ub_scroll_up(int count); | ||
107 | void grey_ub_scroll_down(int count); | ||
108 | |||
109 | /*** Internal stuff ***/ | ||
110 | |||
111 | /* flag definitions */ | ||
112 | #define _GREY_RUNNING 0x0001 /* greyscale overlay is running */ | ||
113 | #define _GREY_DEFERRED_UPDATE 0x0002 /* lcd_update() requested */ | ||
114 | |||
115 | /* fast unsigned multiplication (16x16bit->32bit or 32x32bit->32bit, | ||
116 | * whichever is faster for the architecture) */ | ||
117 | #ifdef CPU_ARM | ||
118 | #define _GREY_MULUQ(a, b) ((uint32_t) (((uint32_t) (a)) * ((uint32_t) (b)))) | ||
119 | #else | ||
120 | #define _GREY_MULUQ(a, b) ((uint32_t) (((uint16_t) (a)) * ((uint16_t) (b)))) | ||
121 | #endif | ||
122 | |||
123 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
124 | #define _GREY_X_ADVANCE sizeof(struct grey_data) | ||
125 | #else | ||
126 | #if LCD_DEPTH == 1 | ||
127 | #define _GREY_X_ADVANCE (8*sizeof(struct grey_data)) | ||
128 | #elif LCD_DEPTH == 2 | ||
129 | #define _GREY_X_ADVANCE (4*sizeof(struct grey_data)) | ||
130 | #endif | ||
131 | #endif /* LCD_PIXELFORMAT */ | ||
132 | |||
133 | /* The greyscale buffer management structure */ | ||
134 | struct _grey_info | ||
135 | { | ||
136 | int x; | ||
137 | int y; | ||
138 | int width; | ||
139 | int height; | ||
140 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
141 | int bx; /* 8-pixel units */ | ||
142 | int bwidth; /* 8-pixel units */ | ||
143 | #else /* vertical packing */ | ||
144 | int by; /* 4-pixel or 8-pixel units */ | ||
145 | int bheight; /* 4-pixel or 8-pixel units */ | ||
146 | #endif | ||
147 | unsigned long flags; /* various flags, see #defines */ | ||
148 | #ifndef SIMULATOR | ||
149 | struct grey_data *data; /* start of greyscale display data */ | ||
150 | #endif | ||
151 | unsigned char *buffer; /* start of chunky pixel buffer (for buffered mode) */ | ||
152 | unsigned char gvalue[256]; /* calculated brightness -> greyvalue table */ | ||
153 | int fg_val; /* current foreground value */ | ||
154 | int bg_val; /* current background value */ | ||
155 | int fg_brightness; /* current foreground brightness */ | ||
156 | int bg_brightness; /* current background brightness */ | ||
157 | int drawmode; /* current draw mode */ | ||
158 | int curfont; /* current selected font */ | ||
159 | }; | ||
160 | |||
161 | /* Global variables */ | ||
162 | extern struct plugin_api *_grey_rb; | ||
163 | extern struct _grey_info _grey_info; | ||
164 | |||
165 | #endif /* HAVE_LCD_BITMAP && (LCD_DEPTH < 4) */ | ||
166 | #endif /* __GREY_H__ */ | ||
diff --git a/apps/plugins/lib/grey_core.c b/apps/plugins/lib/grey_core.c new file mode 100644 index 0000000000..b3ab640602 --- /dev/null +++ b/apps/plugins/lib/grey_core.c | |||
@@ -0,0 +1,767 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * New greyscale framework | ||
11 | * Core & miscellaneous functions | ||
12 | * | ||
13 | * This is a generic framework to display 129 shades of grey on low-depth | ||
14 | * bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. | ||
15 | * | ||
16 | * Copyright (C) 2008 Jens Arnold | ||
17 | * | ||
18 | * All files in this archive are subject to the GNU General Public License. | ||
19 | * See the file COPYING in the source tree root for full license agreement. | ||
20 | * | ||
21 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
22 | * KIND, either express or implied. | ||
23 | * | ||
24 | ****************************************************************************/ | ||
25 | |||
26 | #include "plugin.h" | ||
27 | #include "grey.h" | ||
28 | |||
29 | #if defined(CPU_PP) && defined(HAVE_ADJUSTABLE_CPU_FREQ) | ||
30 | #define NEED_BOOST | ||
31 | #endif | ||
32 | |||
33 | /* Global variables */ | ||
34 | struct plugin_api *_grey_rb = NULL; /* global api struct pointer */ | ||
35 | struct _grey_info _grey_info; /* global info structure */ | ||
36 | |||
37 | #ifndef SIMULATOR | ||
38 | |||
39 | #if CONFIG_LCD == LCD_SSD1815 || CONFIG_LCD == LCD_IFP7XX | ||
40 | /* measured and interpolated curve */ | ||
41 | /* TODO: check for iFP */ | ||
42 | static const unsigned char lcdlinear[256] = { | ||
43 | 0, 3, 5, 8, 11, 13, 16, 18, | ||
44 | 21, 23, 26, 28, 31, 33, 36, 38, | ||
45 | 40, 42, 45, 47, 49, 51, 53, 55, | ||
46 | 57, 59, 60, 62, 64, 66, 67, 69, | ||
47 | 70, 72, 73, 74, 76, 77, 78, 79, | ||
48 | 81, 82, 83, 84, 85, 86, 87, 88, | ||
49 | 88, 89, 90, 91, 92, 92, 93, 94, | ||
50 | 95, 95, 96, 97, 97, 98, 99, 99, | ||
51 | 100, 101, 102, 102, 103, 104, 104, 105, | ||
52 | 106, 106, 107, 107, 108, 109, 109, 110, | ||
53 | 111, 111, 112, 113, 113, 114, 114, 115, | ||
54 | 116, 116, 117, 117, 118, 119, 119, 120, | ||
55 | 120, 121, 121, 122, 122, 123, 123, 124, | ||
56 | 124, 125, 125, 126, 126, 127, 127, 128, | ||
57 | 128, 128, 129, 129, 130, 130, 131, 131, | ||
58 | 132, 132, 133, 133, 133, 134, 134, 135, | ||
59 | 135, 136, 136, 137, 137, 138, 138, 138, | ||
60 | 139, 139, 140, 140, 141, 141, 142, 142, | ||
61 | 143, 143, 144, 144, 145, 145, 146, 146, | ||
62 | 147, 147, 148, 148, 148, 149, 149, 150, | ||
63 | 150, 151, 151, 152, 152, 153, 153, 153, | ||
64 | 154, 154, 155, 155, 156, 156, 157, 157, | ||
65 | 158, 158, 158, 159, 159, 160, 160, 161, | ||
66 | 161, 162, 162, 163, 163, 164, 164, 165, | ||
67 | 165, 166, 167, 167, 168, 168, 169, 169, | ||
68 | 170, 171, 171, 172, 173, 173, 174, 175, | ||
69 | 176, 176, 177, 178, 179, 180, 181, 181, | ||
70 | 182, 183, 184, 185, 186, 188, 189, 190, | ||
71 | 191, 192, 194, 195, 196, 198, 199, 201, | ||
72 | 202, 204, 205, 207, 209, 211, 213, 215, | ||
73 | 217, 219, 222, 224, 226, 229, 231, 234, | ||
74 | 236, 239, 242, 244, 247, 250, 252, 255 | ||
75 | }; | ||
76 | #elif CONFIG_LCD == LCD_S1D15E06 | ||
77 | /* measured and interpolated curve */ | ||
78 | static const unsigned char lcdlinear[256] = { | ||
79 | 0, 5, 11, 16, 21, 27, 32, 37, | ||
80 | 42, 47, 51, 56, 60, 64, 68, 72, | ||
81 | 75, 78, 81, 84, 87, 89, 91, 93, | ||
82 | 95, 96, 98, 99, 101, 102, 103, 104, | ||
83 | 105, 106, 107, 108, 109, 110, 111, 111, | ||
84 | 112, 113, 113, 114, 115, 115, 116, 117, | ||
85 | 117, 118, 118, 119, 119, 120, 120, 121, | ||
86 | 121, 122, 122, 123, 123, 124, 124, 125, | ||
87 | 125, 126, 126, 127, 127, 127, 128, 128, | ||
88 | 129, 129, 130, 130, 131, 131, 132, 132, | ||
89 | 133, 133, 134, 134, 135, 135, 136, 136, | ||
90 | 137, 137, 138, 138, 138, 139, 139, 140, | ||
91 | 140, 141, 141, 141, 142, 142, 143, 143, | ||
92 | 143, 144, 144, 145, 145, 145, 146, 146, | ||
93 | 146, 147, 147, 147, 148, 148, 149, 149, | ||
94 | 149, 150, 150, 150, 151, 151, 151, 152, | ||
95 | 152, 153, 153, 153, 154, 154, 155, 155, | ||
96 | 155, 156, 156, 157, 157, 157, 158, 158, | ||
97 | 159, 159, 159, 160, 160, 161, 161, 162, | ||
98 | 162, 162, 163, 163, 164, 164, 164, 165, | ||
99 | 165, 166, 166, 167, 167, 167, 168, 168, | ||
100 | 169, 169, 170, 170, 170, 171, 171, 172, | ||
101 | 172, 173, 173, 174, 174, 175, 175, 176, | ||
102 | 176, 177, 177, 178, 178, 179, 179, 180, | ||
103 | 180, 181, 182, 182, 183, 184, 184, 185, | ||
104 | 186, 186, 187, 188, 188, 189, 190, 191, | ||
105 | 191, 192, 193, 194, 195, 196, 196, 197, | ||
106 | 198, 199, 200, 201, 202, 203, 204, 205, | ||
107 | 206, 207, 208, 209, 210, 211, 213, 214, | ||
108 | 215, 216, 218, 219, 220, 222, 223, 225, | ||
109 | 227, 228, 230, 232, 233, 235, 237, 239, | ||
110 | 241, 243, 245, 247, 249, 251, 253, 255 | ||
111 | }; | ||
112 | #elif (CONFIG_LCD == LCD_IPOD2BPP) || (CONFIG_LCD == LCD_IPODMINI) | ||
113 | /* measured and interpolated curve for mini LCD */ | ||
114 | /* TODO: verify this curve on the fullsize greyscale LCD */ | ||
115 | static const unsigned char lcdlinear[256] = { | ||
116 | 0, 3, 6, 8, 11, 14, 17, 19, | ||
117 | 22, 24, 27, 29, 32, 34, 36, 38, | ||
118 | 40, 42, 44, 45, 47, 48, 50, 51, | ||
119 | 52, 54, 55, 56, 57, 58, 58, 59, | ||
120 | 60, 61, 62, 62, 63, 64, 64, 65, | ||
121 | 66, 66, 67, 67, 68, 68, 69, 69, | ||
122 | 70, 70, 70, 71, 71, 71, 72, 72, | ||
123 | 73, 73, 73, 74, 74, 74, 74, 75, | ||
124 | 75, 75, 76, 76, 76, 77, 77, 77, | ||
125 | 78, 78, 78, 79, 79, 79, 80, 80, | ||
126 | 80, 80, 81, 81, 81, 82, 82, 82, | ||
127 | 83, 83, 83, 84, 84, 84, 85, 85, | ||
128 | 85, 85, 86, 86, 86, 87, 87, 87, | ||
129 | 87, 88, 88, 88, 89, 89, 89, 89, | ||
130 | 90, 90, 90, 91, 91, 91, 92, 92, | ||
131 | 92, 93, 93, 93, 94, 94, 94, 95, | ||
132 | 95, 96, 96, 96, 97, 97, 98, 98, | ||
133 | 99, 99, 99, 100, 100, 101, 101, 102, | ||
134 | 102, 103, 103, 104, 104, 105, 105, 106, | ||
135 | 106, 107, 107, 108, 108, 109, 109, 110, | ||
136 | 110, 111, 111, 112, 113, 113, 114, 114, | ||
137 | 115, 115, 116, 117, 117, 118, 118, 119, | ||
138 | 120, 120, 121, 122, 122, 123, 124, 124, | ||
139 | 125, 126, 126, 127, 128, 128, 129, 130, | ||
140 | 131, 131, 132, 133, 134, 134, 135, 136, | ||
141 | 137, 138, 139, 140, 141, 142, 143, 144, | ||
142 | 145, 146, 147, 148, 149, 150, 152, 153, | ||
143 | 154, 156, 157, 159, 160, 162, 163, 165, | ||
144 | 167, 168, 170, 172, 174, 176, 178, 180, | ||
145 | 182, 184, 187, 189, 192, 194, 197, 200, | ||
146 | 203, 206, 209, 212, 215, 219, 222, 226, | ||
147 | 229, 233, 236, 240, 244, 248, 251, 255 | ||
148 | }; | ||
149 | #endif | ||
150 | #else /* SIMULATOR */ | ||
151 | /* undo a (generic) PC display gamma of 2.0 to simulate target behaviour */ | ||
152 | static const unsigned char lcdlinear[256] = { | ||
153 | 0, 16, 23, 28, 32, 36, 39, 42, | ||
154 | 45, 48, 50, 53, 55, 58, 60, 62, | ||
155 | 64, 66, 68, 70, 71, 73, 75, 77, | ||
156 | 78, 80, 81, 83, 84, 86, 87, 89, | ||
157 | 90, 92, 93, 94, 96, 97, 98, 100, | ||
158 | 101, 102, 103, 105, 106, 107, 108, 109, | ||
159 | 111, 112, 113, 114, 115, 116, 117, 118, | ||
160 | 119, 121, 122, 123, 124, 125, 126, 127, | ||
161 | 128, 129, 130, 131, 132, 133, 134, 135, | ||
162 | 135, 136, 137, 138, 139, 140, 141, 142, | ||
163 | 143, 144, 145, 145, 146, 147, 148, 149, | ||
164 | 150, 151, 151, 152, 153, 154, 155, 156, | ||
165 | 156, 157, 158, 159, 160, 160, 161, 162, | ||
166 | 163, 164, 164, 165, 166, 167, 167, 168, | ||
167 | 169, 170, 170, 171, 172, 173, 173, 174, | ||
168 | 175, 176, 176, 177, 178, 179, 179, 180, | ||
169 | 181, 181, 182, 183, 183, 184, 185, 186, | ||
170 | 186, 187, 188, 188, 189, 190, 190, 191, | ||
171 | 192, 192, 193, 194, 194, 195, 196, 196, | ||
172 | 197, 198, 198, 199, 199, 200, 201, 201, | ||
173 | 202, 203, 203, 204, 204, 205, 206, 206, | ||
174 | 207, 208, 208, 209, 209, 210, 211, 211, | ||
175 | 212, 212, 213, 214, 214, 215, 215, 216, | ||
176 | 217, 217, 218, 218, 219, 220, 220, 221, | ||
177 | 221, 222, 222, 223, 224, 224, 225, 225, | ||
178 | 226, 226, 227, 228, 228, 229, 229, 230, | ||
179 | 230, 231, 231, 232, 233, 233, 234, 234, | ||
180 | 235, 235, 236, 236, 237, 237, 238, 238, | ||
181 | 239, 240, 240, 241, 241, 242, 242, 243, | ||
182 | 243, 244, 244, 245, 245, 246, 246, 247, | ||
183 | 247, 248, 248, 249, 249, 250, 250, 251, | ||
184 | 251, 252, 252, 253, 253, 254, 254, 255 | ||
185 | }; | ||
186 | #endif /* SIMULATOR */ | ||
187 | |||
188 | /* Prototypes */ | ||
189 | static inline void _deferred_update(void) __attribute__ ((always_inline)); | ||
190 | static int exp_s16p16(int x); | ||
191 | static int log_s16p16(int x); | ||
192 | static void grey_screendump_hook(int fd); | ||
193 | #ifdef SIMULATOR | ||
194 | static unsigned long _grey_get_pixel(int x, int y); | ||
195 | #else | ||
196 | static void _timer_isr(void); | ||
197 | #endif | ||
198 | |||
199 | /* Update LCD areas not covered by the greyscale overlay */ | ||
200 | static inline void _deferred_update(void) | ||
201 | { | ||
202 | int x1 = MAX(_grey_info.x, 0); | ||
203 | int x2 = MIN(_grey_info.x + _grey_info.width, LCD_WIDTH); | ||
204 | int y1 = MAX(_grey_info.y, 0); | ||
205 | int y2 = MIN(_grey_info.y + _grey_info.height, LCD_HEIGHT); | ||
206 | |||
207 | if (y1 > 0) /* refresh part above overlay, full width */ | ||
208 | _grey_rb->lcd_update_rect(0, 0, LCD_WIDTH, y1); | ||
209 | |||
210 | if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */ | ||
211 | _grey_rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2); | ||
212 | |||
213 | if (x1 > 0) /* refresh part to the left of overlay */ | ||
214 | _grey_rb->lcd_update_rect(0, y1, x1, y2 - y1); | ||
215 | |||
216 | if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */ | ||
217 | _grey_rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1); | ||
218 | } | ||
219 | |||
220 | #ifndef SIMULATOR | ||
221 | /* Timer interrupt handler: display next frame */ | ||
222 | static void _timer_isr(void) | ||
223 | { | ||
224 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
225 | _grey_rb->lcd_grey_phase_blit(_grey_info.data, _grey_info.bx, _grey_info.y, | ||
226 | _grey_info.bwidth, _grey_info.height, | ||
227 | _grey_info.width); | ||
228 | #else | ||
229 | _grey_rb->lcd_grey_phase_blit(_grey_info.data, _grey_info.x, _grey_info.by, | ||
230 | _grey_info.width, _grey_info.bheight, | ||
231 | _grey_info.width); | ||
232 | #endif | ||
233 | |||
234 | if (_grey_info.flags & _GREY_DEFERRED_UPDATE) /* lcd_update() requested? */ | ||
235 | { | ||
236 | _deferred_update(); | ||
237 | _grey_info.flags &= ~_GREY_DEFERRED_UPDATE; /* clear request */ | ||
238 | } | ||
239 | } | ||
240 | #endif /* !SIMULATOR */ | ||
241 | |||
242 | /* fixed point exp() */ | ||
243 | static int exp_s16p16(int x) | ||
244 | { | ||
245 | int t; | ||
246 | int y = 0x00010000; | ||
247 | |||
248 | if (x < 0) x += 0xb1721, y >>= 16; | ||
249 | t = x - 0x58b91; if (t >= 0) x = t, y <<= 8; | ||
250 | t = x - 0x2c5c8; if (t >= 0) x = t, y <<= 4; | ||
251 | t = x - 0x162e4; if (t >= 0) x = t, y <<= 2; | ||
252 | t = x - 0x0b172; if (t >= 0) x = t, y <<= 1; | ||
253 | t = x - 0x067cd; if (t >= 0) x = t, y += y >> 1; | ||
254 | t = x - 0x03920; if (t >= 0) x = t, y += y >> 2; | ||
255 | t = x - 0x01e27; if (t >= 0) x = t, y += y >> 3; | ||
256 | t = x - 0x00f85; if (t >= 0) x = t, y += y >> 4; | ||
257 | t = x - 0x007e1; if (t >= 0) x = t, y += y >> 5; | ||
258 | t = x - 0x003f8; if (t >= 0) x = t, y += y >> 6; | ||
259 | t = x - 0x001fe; if (t >= 0) x = t, y += y >> 7; | ||
260 | y += ((y >> 8) * x) >> 8; | ||
261 | |||
262 | return y; | ||
263 | } | ||
264 | |||
265 | /* fixed point log() */ | ||
266 | static int log_s16p16(int x) | ||
267 | { | ||
268 | int t; | ||
269 | int y = 0xa65af; | ||
270 | |||
271 | if (x < 0x00008000) x <<=16, y -= 0xb1721; | ||
272 | if (x < 0x00800000) x <<= 8, y -= 0x58b91; | ||
273 | if (x < 0x08000000) x <<= 4, y -= 0x2c5c8; | ||
274 | if (x < 0x20000000) x <<= 2, y -= 0x162e4; | ||
275 | if (x < 0x40000000) x <<= 1, y -= 0x0b172; | ||
276 | t = x + (x >> 1); if ((t & 0x80000000) == 0) x = t, y -= 0x067cd; | ||
277 | t = x + (x >> 2); if ((t & 0x80000000) == 0) x = t, y -= 0x03920; | ||
278 | t = x + (x >> 3); if ((t & 0x80000000) == 0) x = t, y -= 0x01e27; | ||
279 | t = x + (x >> 4); if ((t & 0x80000000) == 0) x = t, y -= 0x00f85; | ||
280 | t = x + (x >> 5); if ((t & 0x80000000) == 0) x = t, y -= 0x007e1; | ||
281 | t = x + (x >> 6); if ((t & 0x80000000) == 0) x = t, y -= 0x003f8; | ||
282 | t = x + (x >> 7); if ((t & 0x80000000) == 0) x = t, y -= 0x001fe; | ||
283 | x = 0x80000000 - x; | ||
284 | y -= x >> 15; | ||
285 | |||
286 | return y; | ||
287 | } | ||
288 | |||
289 | /* Initialise the framework and prepare the greyscale display buffer | ||
290 | |||
291 | arguments: | ||
292 | newrb = pointer to plugin api | ||
293 | gbuf = pointer to the memory area to use (e.g. plugin buffer) | ||
294 | gbuf_size = max usable size of the buffer | ||
295 | buffered = use chunky pixel buffering? | ||
296 | This allows to use all drawing functions, but needs more | ||
297 | memory. Unbuffered operation provides only a subset of | ||
298 | drawing functions. (only grey_bitmap drawing and scrolling) | ||
299 | width = width in pixels (1..LCD_WIDTH) | ||
300 | height = height in pixels (1..LCD_HEIGHT) | ||
301 | Note that depending on the target LCD, either height or | ||
302 | width are rounded up to a multiple of 4 or 8. | ||
303 | |||
304 | result: | ||
305 | true on success, false on failure | ||
306 | |||
307 | If you need info about the memory taken by the greyscale buffer, supply a | ||
308 | long* as the last parameter. This long will then contain the number of bytes | ||
309 | used. The total memory needed can be calculated as follows: | ||
310 | total_mem = | ||
311 | width * height * 2 [grey display data] | ||
312 | + buffered ? (width * height) : 0 [chunky buffer] | ||
313 | + 0..3 [alignment] | ||
314 | |||
315 | The function is authentic regarding memory usage on the simulator, even | ||
316 | if it doesn't use all of the allocated memory. */ | ||
317 | bool grey_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size, | ||
318 | bool buffered, int width, int height, long *buf_taken) | ||
319 | { | ||
320 | int bdim, i; | ||
321 | long plane_size, buftaken; | ||
322 | unsigned data; | ||
323 | #ifndef SIMULATOR | ||
324 | struct grey_data *grey_data, *grey_end; | ||
325 | #endif | ||
326 | |||
327 | _grey_rb = newrb; | ||
328 | |||
329 | if ((unsigned) width > LCD_WIDTH | ||
330 | || (unsigned) height > LCD_HEIGHT) | ||
331 | return false; | ||
332 | |||
333 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
334 | bdim = (width + 7) >> 3; | ||
335 | width = bdim << 3; | ||
336 | #else /* vertical packing */ | ||
337 | #if LCD_DEPTH == 1 | ||
338 | bdim = (height + 7) >> 3; | ||
339 | height = bdim << 3; | ||
340 | #elif LCD_DEPTH == 2 | ||
341 | bdim = (height + 3) >> 2; | ||
342 | height = bdim << 2; | ||
343 | #endif | ||
344 | #endif | ||
345 | |||
346 | /* the buffer has to be long aligned */ | ||
347 | buftaken = (-(long)gbuf) & 3; | ||
348 | gbuf += buftaken; | ||
349 | |||
350 | plane_size = _GREY_MULUQ(width, height); | ||
351 | |||
352 | if (buffered) /* chunky buffer */ | ||
353 | { | ||
354 | buftaken += plane_size; | ||
355 | _grey_info.buffer = gbuf; | ||
356 | gbuf += plane_size; | ||
357 | } | ||
358 | buftaken += sizeof(struct grey_data) * plane_size; | ||
359 | if (buftaken > gbuf_size) | ||
360 | return false; | ||
361 | |||
362 | #ifdef SIMULATOR | ||
363 | _grey_info.buffer = gbuf; | ||
364 | #else | ||
365 | grey_data = (struct grey_data *)gbuf; | ||
366 | grey_end = grey_data + plane_size; | ||
367 | _grey_info.data = grey_data; | ||
368 | |||
369 | while (grey_data < grey_end) | ||
370 | { | ||
371 | grey_data->phase = _grey_rb->rand() & 0xff; | ||
372 | grey_data->value = 128; /* init to white */ | ||
373 | grey_data++; | ||
374 | } | ||
375 | #endif | ||
376 | |||
377 | _grey_info.x = 0; | ||
378 | _grey_info.y = 0; | ||
379 | _grey_info.width = width; | ||
380 | _grey_info.height = height; | ||
381 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
382 | _grey_info.bx = 0; | ||
383 | _grey_info.bwidth = bdim; | ||
384 | #else | ||
385 | _grey_info.by = 0; | ||
386 | _grey_info.bheight = bdim; | ||
387 | #endif | ||
388 | _grey_info.flags = 0; | ||
389 | _grey_info.fg_val = 0; | ||
390 | _grey_info.bg_val = 128; | ||
391 | _grey_info.fg_brightness = 0; | ||
392 | _grey_info.bg_brightness = 255; | ||
393 | _grey_info.drawmode = DRMODE_SOLID; | ||
394 | _grey_info.curfont = FONT_SYSFIXED; | ||
395 | |||
396 | |||
397 | /* precalculate the value -> pattern index conversion table, taking | ||
398 | linearisation and gamma correction into account */ | ||
399 | for (i = 0; i < 256; i++) | ||
400 | { | ||
401 | data = exp_s16p16(((2<<8) * log_s16p16(i * 257 + 1)) >> 8) + 128; | ||
402 | data = (data - (data >> 8)) >> 8; /* approx. data /= 257 */ | ||
403 | data = (lcdlinear[data] << 7) + 127; | ||
404 | _grey_info.gvalue[i] = (data + (data >> 8)) >> 8; | ||
405 | /* approx. data / 255 */ | ||
406 | } | ||
407 | |||
408 | if (buf_taken) /* caller requested info about space taken */ | ||
409 | *buf_taken = buftaken; | ||
410 | |||
411 | return true; | ||
412 | } | ||
413 | |||
414 | /* Release the greyscale display buffer and the library | ||
415 | DO CALL either this function or at least grey_show_display(false) | ||
416 | before you exit, otherwise nasty things may happen. */ | ||
417 | void grey_release(void) | ||
418 | { | ||
419 | grey_show(false); | ||
420 | } | ||
421 | |||
422 | /* Switch the greyscale overlay on or off | ||
423 | DO NOT call lcd_update() or any other api function that directly accesses | ||
424 | the lcd while the greyscale overlay is running! If you need to do | ||
425 | lcd_update() to update something outside the greyscale overlay area, use | ||
426 | grey_deferred_update() instead. | ||
427 | |||
428 | Other functions to avoid are: | ||
429 | lcd_blit() (obviously), lcd_update_rect(), lcd_set_contrast(), | ||
430 | lcd_set_invert_display(), lcd_set_flip() */ | ||
431 | void grey_show(bool enable) | ||
432 | { | ||
433 | if (enable && !(_grey_info.flags & _GREY_RUNNING)) | ||
434 | { | ||
435 | _grey_info.flags |= _GREY_RUNNING; | ||
436 | #ifdef SIMULATOR | ||
437 | _grey_rb->sim_lcd_ex_init(129, _grey_get_pixel); | ||
438 | grey_update(); | ||
439 | #else /* !SIMULATOR */ | ||
440 | #ifdef NEED_BOOST | ||
441 | _grey_rb->cpu_boost(true); | ||
442 | #endif | ||
443 | #if CONFIG_LCD == LCD_SSD1815 | ||
444 | _grey_rb->timer_register(1, NULL, TIMER_FREQ / 67, 1, _timer_isr); | ||
445 | #elif CONFIG_LCD == LCD_S1D15E06 | ||
446 | _grey_rb->timer_register(1, NULL, TIMER_FREQ / 70, 1, _timer_isr); | ||
447 | #elif CONFIG_LCD == LCD_IPOD2BPP | ||
448 | #ifdef IPOD_1G2G | ||
449 | _grey_rb->timer_register(1, NULL, TIMER_FREQ / 95, 1, _timer_isr); /* verified */ | ||
450 | #elif defined IPOD_3G | ||
451 | _grey_rb->timer_register(1, NULL, TIMER_FREQ / 87, 1, _timer_isr); /* verified */ | ||
452 | #else | ||
453 | /* FIXME: verify value */ | ||
454 | _grey_rb->timer_register(1, NULL, TIMER_FREQ / 80, 1, _timer_isr); | ||
455 | #endif | ||
456 | #elif CONFIG_LCD == LCD_IPODMINI | ||
457 | _grey_rb->timer_register(1, NULL, TIMER_FREQ / 88, 1, _timer_isr); | ||
458 | #elif CONFIG_LCD == LCD_IFP7XX | ||
459 | _grey_rb->timer_register(1, NULL, TIMER_FREQ / 83, 1, _timer_isr); | ||
460 | #endif /* CONFIG_LCD */ | ||
461 | #endif /* !SIMULATOR */ | ||
462 | _grey_rb->screen_dump_set_hook(grey_screendump_hook); | ||
463 | } | ||
464 | else if (!enable && (_grey_info.flags & _GREY_RUNNING)) | ||
465 | { | ||
466 | #ifdef SIMULATOR | ||
467 | _grey_rb->sim_lcd_ex_init(0, NULL); | ||
468 | #else | ||
469 | _grey_rb->timer_unregister(); | ||
470 | #ifdef NEED_BOOST | ||
471 | _grey_rb->cpu_boost(false); | ||
472 | #endif | ||
473 | #endif | ||
474 | _grey_info.flags &= ~_GREY_RUNNING; | ||
475 | _grey_rb->screen_dump_set_hook(NULL); | ||
476 | _grey_rb->lcd_update(); /* restore whatever there was before */ | ||
477 | } | ||
478 | } | ||
479 | |||
480 | #ifdef SIMULATOR | ||
481 | /* Callback function for grey_update_rect() to read a pixel from the greybuffer. | ||
482 | Note that x and y are in LCD coordinates, not greybuffer coordinates! */ | ||
483 | static unsigned long _grey_get_pixel(int x, int y) | ||
484 | { | ||
485 | return _grey_info.buffer[(y - _grey_info.y) * _grey_info.width | ||
486 | + x - _grey_info.x] + (1 << LCD_DEPTH); | ||
487 | } | ||
488 | |||
489 | /* Update a rectangular area of the greyscale overlay */ | ||
490 | void grey_update_rect(int x, int y, int width, int height) | ||
491 | { | ||
492 | if (x + width > _grey_info.width) | ||
493 | width = _grey_info.width - x; | ||
494 | if (y + height > _grey_info.height) | ||
495 | height = _grey_info.height - y; | ||
496 | |||
497 | x += _grey_info.x; | ||
498 | y += _grey_info.y; | ||
499 | |||
500 | if (x + width > LCD_WIDTH) | ||
501 | width = LCD_WIDTH - x; | ||
502 | if (y + height > LCD_HEIGHT) | ||
503 | height = LCD_HEIGHT - y; | ||
504 | |||
505 | _grey_rb->sim_lcd_ex_update_rect(x, y, width, height); | ||
506 | } | ||
507 | |||
508 | #else /* !SIMULATOR */ | ||
509 | |||
510 | void grey_update_rect(int x, int y, int width, int height) | ||
511 | { | ||
512 | unsigned char *src; | ||
513 | |||
514 | if ((width <= 0) || (height <= 0)) | ||
515 | return; /* nothing to do */ | ||
516 | |||
517 | if (y + height > _grey_info.height) | ||
518 | height = _grey_info.height - y; | ||
519 | if (x + width > _grey_info.width) | ||
520 | width = _grey_info.width - x; | ||
521 | |||
522 | src = _grey_info.buffer + _GREY_MULUQ(_grey_info.width, y) + x; | ||
523 | |||
524 | do | ||
525 | { | ||
526 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
527 | int idx = _GREY_MULUQ(_grey_info.width, y) + x; | ||
528 | #else | ||
529 | #if LCD_DEPTH == 1 | ||
530 | int idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (x << 3) + (~y & 7); | ||
531 | #elif LCD_DEPTH == 2 | ||
532 | int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3); | ||
533 | #endif | ||
534 | #endif /* LCD_PIXELFORMAT */ | ||
535 | unsigned char *dst_row = &_grey_info.data[idx].value; | ||
536 | unsigned char *src_row = src; | ||
537 | unsigned char *src_end = src + width; | ||
538 | |||
539 | do | ||
540 | { | ||
541 | *dst_row = *src_row++; | ||
542 | dst_row += _GREY_X_ADVANCE; | ||
543 | } | ||
544 | while (src_row < src_end); | ||
545 | |||
546 | y++; | ||
547 | src += _grey_info.width; | ||
548 | } | ||
549 | while (--height > 0); | ||
550 | } | ||
551 | |||
552 | #endif /* !SIMULATOR */ | ||
553 | |||
554 | /* Update the whole greyscale overlay */ | ||
555 | void grey_update(void) | ||
556 | { | ||
557 | grey_update_rect(0, 0, _grey_info.width, _grey_info.height); | ||
558 | } | ||
559 | |||
560 | /* Do an lcd_update() to show changes done by rb->lcd_xxx() functions | ||
561 | (in areas of the screen not covered by the greyscale overlay). */ | ||
562 | void grey_deferred_lcd_update(void) | ||
563 | { | ||
564 | if (_grey_info.flags & _GREY_RUNNING) | ||
565 | { | ||
566 | #ifdef SIMULATOR | ||
567 | _deferred_update(); | ||
568 | #else | ||
569 | _grey_info.flags |= _GREY_DEFERRED_UPDATE; | ||
570 | #endif | ||
571 | } | ||
572 | else | ||
573 | _grey_rb->lcd_update(); | ||
574 | } | ||
575 | |||
576 | /*** Screenshot ***/ | ||
577 | |||
578 | #define BMP_FIXEDCOLORS (1 << LCD_DEPTH) | ||
579 | #define BMP_VARCOLORS 129 | ||
580 | #define BMP_NUMCOLORS (BMP_FIXEDCOLORS + BMP_VARCOLORS) | ||
581 | #define BMP_BPP 8 | ||
582 | #define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3) | ||
583 | #define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS) | ||
584 | #define BMP_DATASIZE (BMP_LINESIZE * LCD_HEIGHT) | ||
585 | #define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE) | ||
586 | |||
587 | #define LE16_CONST(x) (x)&0xff, ((x)>>8)&0xff | ||
588 | #define LE32_CONST(x) (x)&0xff, ((x)>>8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff | ||
589 | |||
590 | static const unsigned char bmpheader[] = | ||
591 | { | ||
592 | 0x42, 0x4d, /* 'BM' */ | ||
593 | LE32_CONST(BMP_TOTALSIZE), /* Total file size */ | ||
594 | 0x00, 0x00, 0x00, 0x00, /* Reserved */ | ||
595 | LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */ | ||
596 | |||
597 | 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */ | ||
598 | LE32_CONST(LCD_WIDTH), /* Width in pixels */ | ||
599 | LE32_CONST(LCD_HEIGHT), /* Height in pixels */ | ||
600 | 0x01, 0x00, /* Number of planes (always 1) */ | ||
601 | LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */ | ||
602 | 0x00, 0x00, 0x00, 0x00, /* Compression mode, 0 = none */ | ||
603 | LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */ | ||
604 | 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */ | ||
605 | 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */ | ||
606 | LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */ | ||
607 | LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */ | ||
608 | |||
609 | /* Fixed colours */ | ||
610 | #if LCD_DEPTH == 1 | ||
611 | 0x90, 0xee, 0x90, 0x00, /* Colour #0 */ | ||
612 | 0x00, 0x00, 0x00, 0x00 /* Colour #1 */ | ||
613 | #elif LCD_DEPTH == 2 | ||
614 | 0xe6, 0xd8, 0xad, 0x00, /* Colour #0 */ | ||
615 | 0x99, 0x90, 0x73, 0x00, /* Colour #1 */ | ||
616 | 0x4c, 0x48, 0x39, 0x00, /* Colour #2 */ | ||
617 | 0x00, 0x00, 0x00, 0x00 /* Colour #3 */ | ||
618 | #endif | ||
619 | }; | ||
620 | |||
621 | #if LCD_DEPTH == 1 | ||
622 | #define BMP_RED 0x90 | ||
623 | #define BMP_GREEN 0xee | ||
624 | #define BMP_BLUE 0x90 | ||
625 | #elif LCD_DEPTH == 2 | ||
626 | #define BMP_RED 0xad | ||
627 | #define BMP_GREEN 0xd8 | ||
628 | #define BMP_BLUE 0xe6 | ||
629 | #endif | ||
630 | |||
631 | /* Hook function for core screen_dump() to save the current display | ||
632 | content (b&w and greyscale overlay) to an 8-bit BMP file. */ | ||
633 | static void grey_screendump_hook(int fd) | ||
634 | { | ||
635 | int i; | ||
636 | int x, y, gx, gy; | ||
637 | #if LCD_PIXELFORMAT == VERTICAL_PACKING | ||
638 | #if LCD_DEPTH == 1 | ||
639 | unsigned mask; | ||
640 | #elif LCD_DEPTH == 2 | ||
641 | int shift; | ||
642 | #endif | ||
643 | #endif /* LCD_PIXELFORMAT == VERTICAL_PACKING */ | ||
644 | unsigned char *lcdptr; | ||
645 | unsigned char *clut_entry; | ||
646 | unsigned char linebuf[MAX(4*BMP_VARCOLORS,BMP_LINESIZE)]; | ||
647 | |||
648 | _grey_rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */ | ||
649 | |||
650 | /* build clut */ | ||
651 | _grey_rb->memset(linebuf, 0, 4*BMP_VARCOLORS); | ||
652 | clut_entry = linebuf; | ||
653 | |||
654 | for (i = 0; i <= 128; i++) | ||
655 | { | ||
656 | *clut_entry++ = _GREY_MULUQ(BMP_BLUE, i) >> 7; | ||
657 | *clut_entry++ = _GREY_MULUQ(BMP_GREEN, i) >> 7; | ||
658 | *clut_entry++ = _GREY_MULUQ(BMP_RED, i) >> 7; | ||
659 | clut_entry++; | ||
660 | } | ||
661 | _grey_rb->write(fd, linebuf, 4*BMP_VARCOLORS); | ||
662 | |||
663 | /* BMP image goes bottom -> top */ | ||
664 | for (y = LCD_HEIGHT - 1; y >= 0; y--) | ||
665 | { | ||
666 | _grey_rb->memset(linebuf, 0, BMP_LINESIZE); | ||
667 | |||
668 | gy = y - _grey_info.y; | ||
669 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
670 | #if LCD_DEPTH == 2 | ||
671 | lcdptr = _grey_rb->lcd_framebuffer + _GREY_MULUQ(LCD_FBWIDTH, y); | ||
672 | |||
673 | for (x = 0; x < LCD_WIDTH; x += 4) | ||
674 | { | ||
675 | gx = x - _grey_info.x; | ||
676 | |||
677 | if (((unsigned)gy < (unsigned)_grey_info.height) | ||
678 | && ((unsigned)gx < (unsigned)_grey_info.width)) | ||
679 | { | ||
680 | #ifdef SIMULATOR | ||
681 | unsigned char *src = _grey_info.buffer | ||
682 | + _GREY_MULUQ(_grey_info.width, gy) + gx; | ||
683 | |||
684 | for (i = 0; i < 4; i++) | ||
685 | linebuf[x + i] = BMP_FIXEDCOLORS + *src++; | ||
686 | #else | ||
687 | unsigned char *src = &_grey_info.data[_GREY_MULUQ(_grey_info.width, | ||
688 | gy) + gx].value; | ||
689 | for (i = 0; i < 4; i++) | ||
690 | { | ||
691 | linebuf[x + i] = BMP_FIXEDCOLORS + *src; | ||
692 | src += _GREY_X_ADVANCE; | ||
693 | } | ||
694 | #endif | ||
695 | } | ||
696 | else | ||
697 | { | ||
698 | unsigned data = *lcdptr; | ||
699 | linebuf[x] = (data >> 6) & 3; | ||
700 | linebuf[x + 1] = (data >> 4) & 3; | ||
701 | linebuf[x + 2] = (data >> 2) & 3; | ||
702 | linebuf[x + 3] = data & 3; | ||
703 | } | ||
704 | lcdptr++; | ||
705 | } | ||
706 | #endif /* LCD_DEPTH */ | ||
707 | #else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ | ||
708 | #if LCD_DEPTH == 1 | ||
709 | mask = 1 << (y & 7); | ||
710 | lcdptr = _grey_rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3); | ||
711 | |||
712 | for (x = 0; x < LCD_WIDTH; x++) | ||
713 | { | ||
714 | gx = x - _grey_info.x; | ||
715 | |||
716 | if (((unsigned)gy < (unsigned)_grey_info.height) | ||
717 | && ((unsigned)gx < (unsigned)_grey_info.width)) | ||
718 | { | ||
719 | #ifdef SIMULATOR | ||
720 | linebuf[x] = BMP_FIXEDCOLORS | ||
721 | + _grey_info.buffer[_GREY_MULUQ(_grey_info.width, | ||
722 | gy) + gx]; | ||
723 | #else | ||
724 | linebuf[x] = BMP_FIXEDCOLORS | ||
725 | + _grey_info.data[_GREY_MULUQ(_grey_info.width, | ||
726 | gy & ~7) + (gx << 3) + (~gy & 7)].value; | ||
727 | #endif | ||
728 | } | ||
729 | else | ||
730 | { | ||
731 | linebuf[x] = (*lcdptr & mask) ? 1 : 0; | ||
732 | } | ||
733 | lcdptr++; | ||
734 | } | ||
735 | #elif LCD_DEPTH == 2 | ||
736 | shift = 2 * (y & 3); | ||
737 | lcdptr = _grey_rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 2); | ||
738 | |||
739 | for (x = 0; x < LCD_WIDTH; x++) | ||
740 | { | ||
741 | gx = x - _grey_info.x; | ||
742 | |||
743 | if (((unsigned)gy < (unsigned)_grey_info.height) | ||
744 | && ((unsigned)gx < (unsigned)_grey_info.width)) | ||
745 | { | ||
746 | #ifdef SIMULATOR | ||
747 | linebuf[x] = BMP_FIXEDCOLORS | ||
748 | + _grey_info.buffer[_GREY_MULUQ(_grey_info.width, | ||
749 | gy) + gx]; | ||
750 | #else | ||
751 | linebuf[x] = BMP_FIXEDCOLORS | ||
752 | + _grey_info.data[_GREY_MULUQ(_grey_info.width, | ||
753 | gy & ~3) + (gx << 2) + (~gy & 7)].value; | ||
754 | #endif | ||
755 | } | ||
756 | else | ||
757 | { | ||
758 | linebuf[x] = (*lcdptr >> shift) & 3; | ||
759 | } | ||
760 | lcdptr++; | ||
761 | } | ||
762 | #endif /* LCD_DEPTH */ | ||
763 | #endif /* LCD_PIXELFORMAT */ | ||
764 | |||
765 | _grey_rb->write(fd, linebuf, BMP_LINESIZE); | ||
766 | } | ||
767 | } | ||
diff --git a/apps/plugins/lib/grey_draw.c b/apps/plugins/lib/grey_draw.c new file mode 100644 index 0000000000..e243b5fbce --- /dev/null +++ b/apps/plugins/lib/grey_draw.c | |||
@@ -0,0 +1,681 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * New greyscale framework | ||
11 | * Drawing functions | ||
12 | * | ||
13 | * This is a generic framework to display 129 shades of grey on low-depth | ||
14 | * bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. | ||
15 | * | ||
16 | * Copyright (C) 2008 Jens Arnold | ||
17 | * | ||
18 | * All files in this archive are subject to the GNU General Public License. | ||
19 | * See the file COPYING in the source tree root for full license agreement. | ||
20 | * | ||
21 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
22 | * KIND, either express or implied. | ||
23 | * | ||
24 | ****************************************************************************/ | ||
25 | |||
26 | #include "plugin.h" | ||
27 | #include "grey.h" | ||
28 | |||
29 | /*** low-level drawing functions ***/ | ||
30 | |||
31 | static void setpixel(unsigned char *address) | ||
32 | { | ||
33 | *address = _grey_info.fg_val; | ||
34 | } | ||
35 | |||
36 | static void clearpixel(unsigned char *address) | ||
37 | { | ||
38 | *address = _grey_info.bg_val; | ||
39 | } | ||
40 | |||
41 | static void flippixel(unsigned char *address) | ||
42 | { | ||
43 | *address = 128 - *address; | ||
44 | } | ||
45 | |||
46 | static void nopixel(unsigned char *address) | ||
47 | { | ||
48 | (void)address; | ||
49 | } | ||
50 | |||
51 | void (* const _grey_pixelfuncs[8])(unsigned char *address) = { | ||
52 | flippixel, nopixel, setpixel, setpixel, | ||
53 | nopixel, clearpixel, nopixel, clearpixel | ||
54 | }; | ||
55 | |||
56 | /*** Drawing functions ***/ | ||
57 | |||
58 | /* Clear the whole display */ | ||
59 | void grey_clear_display(void) | ||
60 | { | ||
61 | int value = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
62 | _grey_info.fg_val : _grey_info.bg_val; | ||
63 | |||
64 | _grey_rb->memset(_grey_info.buffer, value, | ||
65 | _GREY_MULUQ(_grey_info.width, _grey_info.height)); | ||
66 | } | ||
67 | |||
68 | /* Set a single pixel */ | ||
69 | void grey_drawpixel(int x, int y) | ||
70 | { | ||
71 | if (((unsigned)x < (unsigned)_grey_info.width) | ||
72 | && ((unsigned)y < (unsigned)_grey_info.height)) | ||
73 | _grey_pixelfuncs[_grey_info.drawmode](&_grey_info.buffer[_GREY_MULUQ( | ||
74 | _grey_info.width, y) + x]); | ||
75 | } | ||
76 | |||
77 | /* Draw a line */ | ||
78 | void grey_drawline(int x1, int y1, int x2, int y2) | ||
79 | { | ||
80 | int numpixels; | ||
81 | int i; | ||
82 | int deltax, deltay; | ||
83 | int d, dinc1, dinc2; | ||
84 | int x, xinc1, xinc2; | ||
85 | int y, yinc1, yinc2; | ||
86 | void (*pfunc)(unsigned char *address) = _grey_pixelfuncs[_grey_info.drawmode]; | ||
87 | |||
88 | deltax = abs(x2 - x1); | ||
89 | deltay = abs(y2 - y1); | ||
90 | xinc2 = 1; | ||
91 | yinc2 = 1; | ||
92 | |||
93 | if (deltax >= deltay) | ||
94 | { | ||
95 | numpixels = deltax; | ||
96 | d = 2 * deltay - deltax; | ||
97 | dinc1 = deltay * 2; | ||
98 | dinc2 = (deltay - deltax) * 2; | ||
99 | xinc1 = 1; | ||
100 | yinc1 = 0; | ||
101 | } | ||
102 | else | ||
103 | { | ||
104 | numpixels = deltay; | ||
105 | d = 2 * deltax - deltay; | ||
106 | dinc1 = deltax * 2; | ||
107 | dinc2 = (deltax - deltay) * 2; | ||
108 | xinc1 = 0; | ||
109 | yinc1 = 1; | ||
110 | } | ||
111 | numpixels++; /* include endpoints */ | ||
112 | |||
113 | if (x1 > x2) | ||
114 | { | ||
115 | xinc1 = -xinc1; | ||
116 | xinc2 = -xinc2; | ||
117 | } | ||
118 | |||
119 | if (y1 > y2) | ||
120 | { | ||
121 | yinc1 = -yinc1; | ||
122 | yinc2 = -yinc2; | ||
123 | } | ||
124 | |||
125 | x = x1; | ||
126 | y = y1; | ||
127 | |||
128 | for (i = 0; i < numpixels; i++) | ||
129 | { | ||
130 | if (((unsigned)x < (unsigned)_grey_info.width) | ||
131 | && ((unsigned)y < (unsigned)_grey_info.height)) | ||
132 | pfunc(&_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]); | ||
133 | |||
134 | if (d < 0) | ||
135 | { | ||
136 | d += dinc1; | ||
137 | x += xinc1; | ||
138 | y += yinc1; | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | d += dinc2; | ||
143 | x += xinc2; | ||
144 | y += yinc2; | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | |||
149 | /* Draw a horizontal line (optimised) */ | ||
150 | void grey_hline(int x1, int x2, int y) | ||
151 | { | ||
152 | int x; | ||
153 | int value = 0; | ||
154 | unsigned char *dst; | ||
155 | bool fillopt = false; | ||
156 | void (*pfunc)(unsigned char *address); | ||
157 | |||
158 | /* direction flip */ | ||
159 | if (x2 < x1) | ||
160 | { | ||
161 | x = x1; | ||
162 | x1 = x2; | ||
163 | x2 = x; | ||
164 | } | ||
165 | |||
166 | /* nothing to draw? */ | ||
167 | if (((unsigned)y >= (unsigned)_grey_info.height) | ||
168 | || (x1 >= _grey_info.width) || (x2 < 0)) | ||
169 | return; | ||
170 | |||
171 | /* clipping */ | ||
172 | if (x1 < 0) | ||
173 | x1 = 0; | ||
174 | if (x2 >= _grey_info.width) | ||
175 | x2 = _grey_info.width - 1; | ||
176 | |||
177 | if (_grey_info.drawmode & DRMODE_INVERSEVID) | ||
178 | { | ||
179 | if (_grey_info.drawmode & DRMODE_BG) | ||
180 | { | ||
181 | fillopt = true; | ||
182 | value = _grey_info.bg_val; | ||
183 | } | ||
184 | } | ||
185 | else | ||
186 | { | ||
187 | if (_grey_info.drawmode & DRMODE_FG) | ||
188 | { | ||
189 | fillopt = true; | ||
190 | value = _grey_info.fg_val; | ||
191 | } | ||
192 | } | ||
193 | pfunc = _grey_pixelfuncs[_grey_info.drawmode]; | ||
194 | dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x1]; | ||
195 | |||
196 | if (fillopt) | ||
197 | _grey_rb->memset(dst, value, x2 - x1 + 1); | ||
198 | else | ||
199 | { | ||
200 | unsigned char *dst_end = dst + x2 - x1; | ||
201 | do | ||
202 | pfunc(dst++); | ||
203 | while (dst <= dst_end); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | /* Draw a vertical line (optimised) */ | ||
208 | void grey_vline(int x, int y1, int y2) | ||
209 | { | ||
210 | int y; | ||
211 | unsigned char *dst, *dst_end; | ||
212 | void (*pfunc)(unsigned char *address); | ||
213 | |||
214 | /* direction flip */ | ||
215 | if (y2 < y1) | ||
216 | { | ||
217 | y = y1; | ||
218 | y1 = y2; | ||
219 | y2 = y; | ||
220 | } | ||
221 | |||
222 | /* nothing to draw? */ | ||
223 | if (((unsigned)x >= (unsigned)_grey_info.width) | ||
224 | || (y1 >= _grey_info.height) || (y2 < 0)) | ||
225 | return; | ||
226 | |||
227 | /* clipping */ | ||
228 | if (y1 < 0) | ||
229 | y1 = 0; | ||
230 | if (y2 >= _grey_info.height) | ||
231 | y2 = _grey_info.height - 1; | ||
232 | |||
233 | pfunc = _grey_pixelfuncs[_grey_info.drawmode]; | ||
234 | dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y1) + x]; | ||
235 | |||
236 | dst_end = dst + _GREY_MULUQ(_grey_info.width, y2 - y1); | ||
237 | do | ||
238 | { | ||
239 | pfunc(dst); | ||
240 | dst += _grey_info.width; | ||
241 | } | ||
242 | while (dst <= dst_end); | ||
243 | } | ||
244 | |||
245 | /* Draw a filled triangle */ | ||
246 | void grey_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3) | ||
247 | { | ||
248 | int x, y; | ||
249 | long fp_x1, fp_x2, fp_dx1, fp_dx2; | ||
250 | |||
251 | /* sort vertices by increasing y value */ | ||
252 | if (y1 > y3) | ||
253 | { | ||
254 | if (y2 < y3) /* y2 < y3 < y1 */ | ||
255 | { | ||
256 | x = x1; x1 = x2; x2 = x3; x3 = x; | ||
257 | y = y1; y1 = y2; y2 = y3; y3 = y; | ||
258 | } | ||
259 | else if (y2 > y1) /* y3 < y1 < y2 */ | ||
260 | { | ||
261 | x = x1; x1 = x3; x3 = x2; x2 = x; | ||
262 | y = y1; y1 = y3; y3 = y2; y2 = y; | ||
263 | } | ||
264 | else /* y3 <= y2 <= y1 */ | ||
265 | { | ||
266 | x = x1; x1 = x3; x3 = x; | ||
267 | y = y1; y1 = y3; y3 = y; | ||
268 | } | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | if (y2 < y1) /* y2 < y1 <= y3 */ | ||
273 | { | ||
274 | x = x1; x1 = x2; x2 = x; | ||
275 | y = y1; y1 = y2; y2 = y; | ||
276 | } | ||
277 | else if (y2 > y3) /* y1 <= y3 < y2 */ | ||
278 | { | ||
279 | x = x2; x2 = x3; x3 = x; | ||
280 | y = y2; y2 = y3; y3 = y; | ||
281 | } | ||
282 | /* else already sorted */ | ||
283 | } | ||
284 | |||
285 | if (y1 < y3) /* draw */ | ||
286 | { | ||
287 | fp_dx1 = ((x3 - x1) << 16) / (y3 - y1); | ||
288 | fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1); | ||
289 | |||
290 | if (y1 < y2) /* first part */ | ||
291 | { | ||
292 | fp_dx2 = ((x2 - x1) << 16) / (y2 - y1); | ||
293 | fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1); | ||
294 | for (y = y1; y < y2; y++) | ||
295 | { | ||
296 | grey_hline(fp_x1 >> 16, fp_x2 >> 16, y); | ||
297 | fp_x1 += fp_dx1; | ||
298 | fp_x2 += fp_dx2; | ||
299 | } | ||
300 | } | ||
301 | if (y2 < y3) /* second part */ | ||
302 | { | ||
303 | fp_dx2 = ((x3 - x2) << 16) / (y3 - y2); | ||
304 | fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1); | ||
305 | for (y = y2; y < y3; y++) | ||
306 | { | ||
307 | grey_hline(fp_x1 >> 16, fp_x2 >> 16, y); | ||
308 | fp_x1 += fp_dx1; | ||
309 | fp_x2 += fp_dx2; | ||
310 | } | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | |||
315 | /* Draw a rectangular box */ | ||
316 | void grey_drawrect(int x, int y, int width, int height) | ||
317 | { | ||
318 | if ((width <= 0) || (height <= 0)) | ||
319 | return; | ||
320 | |||
321 | int x2 = x + width - 1; | ||
322 | int y2 = y + height - 1; | ||
323 | |||
324 | grey_vline(x, y, y2); | ||
325 | grey_vline(x2, y, y2); | ||
326 | grey_hline(x, x2, y); | ||
327 | grey_hline(x, x2, y2); | ||
328 | } | ||
329 | |||
330 | /* Fill a rectangular area */ | ||
331 | void grey_fillrect(int x, int y, int width, int height) | ||
332 | { | ||
333 | int value = 0; | ||
334 | unsigned char *dst, *dst_end; | ||
335 | bool fillopt = false; | ||
336 | void (*pfunc)(unsigned char *address); | ||
337 | |||
338 | /* nothing to draw? */ | ||
339 | if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) | ||
340 | || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0)) | ||
341 | return; | ||
342 | |||
343 | /* clipping */ | ||
344 | if (x < 0) | ||
345 | { | ||
346 | width += x; | ||
347 | x = 0; | ||
348 | } | ||
349 | if (y < 0) | ||
350 | { | ||
351 | height += y; | ||
352 | y = 0; | ||
353 | } | ||
354 | if (x + width > _grey_info.width) | ||
355 | width = _grey_info.width - x; | ||
356 | if (y + height > _grey_info.height) | ||
357 | height = _grey_info.height - y; | ||
358 | |||
359 | if (_grey_info.drawmode & DRMODE_INVERSEVID) | ||
360 | { | ||
361 | if (_grey_info.drawmode & DRMODE_BG) | ||
362 | { | ||
363 | fillopt = true; | ||
364 | value = _grey_info.bg_val; | ||
365 | } | ||
366 | } | ||
367 | else | ||
368 | { | ||
369 | if (_grey_info.drawmode & DRMODE_FG) | ||
370 | { | ||
371 | fillopt = true; | ||
372 | value = _grey_info.fg_val; | ||
373 | } | ||
374 | } | ||
375 | pfunc = _grey_pixelfuncs[_grey_info.drawmode]; | ||
376 | dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; | ||
377 | dst_end = dst + _GREY_MULUQ(_grey_info.width, height); | ||
378 | |||
379 | do | ||
380 | { | ||
381 | if (fillopt) | ||
382 | _grey_rb->memset(dst, value, width); | ||
383 | else | ||
384 | { | ||
385 | unsigned char *dst_row = dst; | ||
386 | unsigned char *row_end = dst_row + width; | ||
387 | |||
388 | do | ||
389 | pfunc(dst_row++); | ||
390 | while (dst_row < row_end); | ||
391 | } | ||
392 | dst += _grey_info.width; | ||
393 | } | ||
394 | while (dst < dst_end); | ||
395 | } | ||
396 | |||
397 | /* About Rockbox' internal monochrome bitmap format: | ||
398 | * | ||
399 | * A bitmap contains one bit for every pixel that defines if that pixel is | ||
400 | * foreground (1) or background (0). Bits within a byte are arranged | ||
401 | * vertically, LSB at top. | ||
402 | * The bytes are stored in row-major order, with byte 0 being top left, | ||
403 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows | ||
404 | * 0..7, the second row defines pixel row 8..15 etc. */ | ||
405 | |||
406 | /* Draw a partial monochrome bitmap */ | ||
407 | void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | ||
408 | int stride, int x, int y, int width, int height) | ||
409 | { | ||
410 | const unsigned char *src_end; | ||
411 | unsigned char *dst, *dst_end; | ||
412 | void (*fgfunc)(unsigned char *address); | ||
413 | void (*bgfunc)(unsigned char *address); | ||
414 | |||
415 | /* nothing to draw? */ | ||
416 | if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) | ||
417 | || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0)) | ||
418 | return; | ||
419 | |||
420 | /* clipping */ | ||
421 | if (x < 0) | ||
422 | { | ||
423 | width += x; | ||
424 | src_x -= x; | ||
425 | x = 0; | ||
426 | } | ||
427 | if (y < 0) | ||
428 | { | ||
429 | height += y; | ||
430 | src_y -= y; | ||
431 | y = 0; | ||
432 | } | ||
433 | if (x + width > _grey_info.width) | ||
434 | width = _grey_info.width - x; | ||
435 | if (y + height > _grey_info.height) | ||
436 | height = _grey_info.height - y; | ||
437 | |||
438 | src += _GREY_MULUQ(stride, src_y >> 3) + src_x; /* move starting point */ | ||
439 | src_y &= 7; | ||
440 | src_end = src + width; | ||
441 | |||
442 | fgfunc = _grey_pixelfuncs[_grey_info.drawmode]; | ||
443 | bgfunc = _grey_pixelfuncs[_grey_info.drawmode ^ DRMODE_INVERSEVID]; | ||
444 | dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; | ||
445 | |||
446 | do | ||
447 | { | ||
448 | const unsigned char *src_col = src++; | ||
449 | unsigned char *dst_col = dst++; | ||
450 | unsigned data = *src_col >> src_y; | ||
451 | int numbits = 8 - src_y; | ||
452 | |||
453 | dst_end = dst_col + _GREY_MULUQ(_grey_info.width, height); | ||
454 | do | ||
455 | { | ||
456 | if (data & 0x01) | ||
457 | fgfunc(dst_col); | ||
458 | else | ||
459 | bgfunc(dst_col); | ||
460 | |||
461 | dst_col += _grey_info.width; | ||
462 | |||
463 | data >>= 1; | ||
464 | if (--numbits == 0) | ||
465 | { | ||
466 | src_col += stride; | ||
467 | data = *src_col; | ||
468 | numbits = 8; | ||
469 | } | ||
470 | } | ||
471 | while (dst_col < dst_end); | ||
472 | } | ||
473 | while (src < src_end); | ||
474 | } | ||
475 | |||
476 | /* Draw a full monochrome bitmap */ | ||
477 | void grey_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) | ||
478 | { | ||
479 | grey_mono_bitmap_part(src, 0, 0, width, x, y, width, height); | ||
480 | } | ||
481 | |||
482 | /* Draw a partial greyscale bitmap, canonical format */ | ||
483 | void grey_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, | ||
484 | int stride, int x, int y, int width, int height) | ||
485 | { | ||
486 | unsigned char *dst, *dst_end; | ||
487 | |||
488 | /* nothing to draw? */ | ||
489 | if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) | ||
490 | || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0)) | ||
491 | return; | ||
492 | |||
493 | /* clipping */ | ||
494 | if (x < 0) | ||
495 | { | ||
496 | width += x; | ||
497 | src_x -= x; | ||
498 | x = 0; | ||
499 | } | ||
500 | if (y < 0) | ||
501 | { | ||
502 | height += y; | ||
503 | src_y -= y; | ||
504 | y = 0; | ||
505 | } | ||
506 | if (x + width > _grey_info.width) | ||
507 | width = _grey_info.width - x; | ||
508 | if (y + height > _grey_info.height) | ||
509 | height = _grey_info.height - y; | ||
510 | |||
511 | src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */ | ||
512 | dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; | ||
513 | dst_end = dst + _GREY_MULUQ(_grey_info.width, height); | ||
514 | |||
515 | do | ||
516 | { | ||
517 | const unsigned char *src_row = src; | ||
518 | unsigned char *dst_row = dst; | ||
519 | unsigned char *row_end = dst_row + width; | ||
520 | |||
521 | do | ||
522 | *dst_row++ = _grey_info.gvalue[*src_row++]; | ||
523 | while (dst_row < row_end); | ||
524 | |||
525 | src += stride; | ||
526 | dst += _grey_info.width; | ||
527 | } | ||
528 | while (dst < dst_end); | ||
529 | } | ||
530 | |||
531 | /* Draw a full greyscale bitmap, canonical format */ | ||
532 | void grey_gray_bitmap(const unsigned char *src, int x, int y, int width, | ||
533 | int height) | ||
534 | { | ||
535 | grey_gray_bitmap_part(src, 0, 0, width, x, y, width, height); | ||
536 | } | ||
537 | |||
538 | /* Put a string at a given pixel position, skipping first ofs pixel columns */ | ||
539 | void grey_putsxyofs(int x, int y, int ofs, const unsigned char *str) | ||
540 | { | ||
541 | int ch; | ||
542 | struct font* pf = _grey_rb->font_get(_grey_info.curfont); | ||
543 | |||
544 | while ((ch = *str++) != '\0' && x < _grey_info.width) | ||
545 | { | ||
546 | int width; | ||
547 | const unsigned char *bits; | ||
548 | |||
549 | /* check input range */ | ||
550 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | ||
551 | ch = pf->defaultchar; | ||
552 | ch -= pf->firstchar; | ||
553 | |||
554 | /* get proportional width and glyph bits */ | ||
555 | width = pf->width ? pf->width[ch] : pf->maxwidth; | ||
556 | |||
557 | if (ofs > width) | ||
558 | { | ||
559 | ofs -= width; | ||
560 | continue; | ||
561 | } | ||
562 | |||
563 | bits = pf->bits + (pf->offset ? | ||
564 | pf->offset[ch] : (((pf->height + 7) >> 3) * pf->maxwidth * ch)); | ||
565 | |||
566 | grey_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); | ||
567 | |||
568 | x += width - ofs; | ||
569 | ofs = 0; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | /* Put a string at a given pixel position */ | ||
574 | void grey_putsxy(int x, int y, const unsigned char *str) | ||
575 | { | ||
576 | grey_putsxyofs(x, y, 0, str); | ||
577 | } | ||
578 | |||
579 | /*** Unbuffered drawing functions ***/ | ||
580 | |||
581 | #ifdef SIMULATOR | ||
582 | |||
583 | /* Clear the whole display */ | ||
584 | void grey_ub_clear_display(void) | ||
585 | { | ||
586 | grey_clear_display(); | ||
587 | grey_update(); | ||
588 | } | ||
589 | |||
590 | /* Draw a partial greyscale bitmap, canonical format */ | ||
591 | void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, | ||
592 | int stride, int x, int y, int width, int height) | ||
593 | { | ||
594 | grey_gray_bitmap_part(src, src_x, src_y, stride, x, y, width, height); | ||
595 | grey_update_rect(x, y, width, height); | ||
596 | } | ||
597 | |||
598 | #else /* !SIMULATOR */ | ||
599 | |||
600 | /* Clear the greyscale display (sets all pixels to white) */ | ||
601 | void grey_ub_clear_display(void) | ||
602 | { | ||
603 | int value = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
604 | _grey_info.fg_val : _grey_info.bg_val; | ||
605 | unsigned char *dst = &_grey_info.data[0].value; | ||
606 | unsigned char *dst_end = dst + sizeof(struct grey_data) | ||
607 | * _GREY_MULUQ(_grey_info.width, _grey_info.height); | ||
608 | |||
609 | do | ||
610 | { | ||
611 | *dst = value; | ||
612 | dst += sizeof(struct grey_data); | ||
613 | } | ||
614 | while (dst < dst_end); | ||
615 | } | ||
616 | |||
617 | /* Draw a partial greyscale bitmap, canonical format */ | ||
618 | void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, | ||
619 | int stride, int x, int y, int width, int height) | ||
620 | { | ||
621 | /* nothing to draw? */ | ||
622 | if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) | ||
623 | || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0)) | ||
624 | return; | ||
625 | |||
626 | /* clipping */ | ||
627 | if (x < 0) | ||
628 | { | ||
629 | width += x; | ||
630 | src_x -= x; | ||
631 | x = 0; | ||
632 | } | ||
633 | if (y < 0) | ||
634 | { | ||
635 | height += y; | ||
636 | src_y -= y; | ||
637 | y = 0; | ||
638 | } | ||
639 | if (x + width > _grey_info.width) | ||
640 | width = _grey_info.width - x; | ||
641 | if (y + height > _grey_info.height) | ||
642 | height = _grey_info.height - y; | ||
643 | |||
644 | src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */ | ||
645 | |||
646 | do | ||
647 | { | ||
648 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
649 | int idx = _GREY_MULUQ(_grey_info.width, y) + x; | ||
650 | #else | ||
651 | #if LCD_DEPTH == 1 | ||
652 | int idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (x << 3) + (~y & 7); | ||
653 | #elif LCD_DEPTH == 2 | ||
654 | int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3); | ||
655 | #endif | ||
656 | #endif /* LCD_PIXELFORMAT */ | ||
657 | unsigned char *dst_row = &_grey_info.data[idx].value; | ||
658 | const unsigned char *src_row = src; | ||
659 | const unsigned char *src_end = src + width; | ||
660 | |||
661 | do | ||
662 | { | ||
663 | *dst_row = _grey_info.gvalue[*src_row++]; | ||
664 | dst_row += _GREY_X_ADVANCE; | ||
665 | } | ||
666 | while (src_row < src_end); | ||
667 | |||
668 | y++; | ||
669 | src += stride; | ||
670 | } | ||
671 | while (--height > 0); | ||
672 | } | ||
673 | |||
674 | #endif /* !SIMULATOR */ | ||
675 | |||
676 | /* Draw a full greyscale bitmap, canonical format */ | ||
677 | void grey_ub_gray_bitmap(const unsigned char *src, int x, int y, int width, | ||
678 | int height) | ||
679 | { | ||
680 | grey_ub_gray_bitmap_part(src, 0, 0, width, x, y, width, height); | ||
681 | } | ||
diff --git a/apps/plugins/lib/grey_parm.c b/apps/plugins/lib/grey_parm.c new file mode 100644 index 0000000000..6d605059f8 --- /dev/null +++ b/apps/plugins/lib/grey_parm.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * New greyscale framework | ||
11 | * Parameter handling | ||
12 | * | ||
13 | * This is a generic framework to display 129 shades of grey on low-depth | ||
14 | * bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. | ||
15 | * | ||
16 | * Copyright (C) 2008 Jens Arnold | ||
17 | * | ||
18 | * All files in this archive are subject to the GNU General Public License. | ||
19 | * See the file COPYING in the source tree root for full license agreement. | ||
20 | * | ||
21 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
22 | * KIND, either express or implied. | ||
23 | * | ||
24 | ****************************************************************************/ | ||
25 | |||
26 | #include "plugin.h" | ||
27 | #include "grey.h" | ||
28 | |||
29 | /* Set position of the top left corner of the greyscale overlay | ||
30 | Note that depending on the target LCD, either x or y gets rounded | ||
31 | to the nearest multiple of 4 or 8 */ | ||
32 | void grey_set_position(int x, int y) | ||
33 | { | ||
34 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
35 | _grey_info.bx = (x + 4) >> 3; | ||
36 | x = 8 * _grey_info.bx; | ||
37 | #else | ||
38 | #if LCD_DEPTH == 1 | ||
39 | _grey_info.by = (y + 4) >> 3; | ||
40 | y = 8 * _grey_info.by; | ||
41 | #elif LCD_DEPTH == 2 | ||
42 | _grey_info.by = (y + 2) >> 2; | ||
43 | y = 4 * _grey_info.by; | ||
44 | #endif | ||
45 | #endif /* LCD_PIXELFORMAT */ | ||
46 | _grey_info.x = x; | ||
47 | _grey_info.y = y; | ||
48 | |||
49 | if (_grey_info.flags & _GREY_RUNNING) | ||
50 | { | ||
51 | #ifdef SIMULATOR | ||
52 | grey_deferred_lcd_update(); | ||
53 | grey_update(); | ||
54 | #else | ||
55 | _grey_info.flags |= _GREY_DEFERRED_UPDATE; | ||
56 | #endif | ||
57 | } | ||
58 | } | ||
59 | |||
60 | /* Set the draw mode for subsequent drawing operations */ | ||
61 | void grey_set_drawmode(int mode) | ||
62 | { | ||
63 | _grey_info.drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | ||
64 | } | ||
65 | |||
66 | /* Return the current draw mode */ | ||
67 | int grey_get_drawmode(void) | ||
68 | { | ||
69 | return _grey_info.drawmode; | ||
70 | } | ||
71 | |||
72 | /* Set the foreground shade for subsequent drawing operations */ | ||
73 | void grey_set_foreground(unsigned brightness) | ||
74 | { | ||
75 | _grey_info.fg_val = _grey_info.gvalue[brightness]; | ||
76 | _grey_info.fg_brightness = brightness; | ||
77 | } | ||
78 | |||
79 | /* Return the current foreground shade */ | ||
80 | unsigned grey_get_foreground(void) | ||
81 | { | ||
82 | return _grey_info.fg_brightness; | ||
83 | } | ||
84 | |||
85 | /* Set the background shade for subsequent drawing operations */ | ||
86 | void grey_set_background(unsigned brightness) | ||
87 | { | ||
88 | _grey_info.bg_val = _grey_info.gvalue[brightness]; | ||
89 | _grey_info.bg_brightness = brightness; | ||
90 | } | ||
91 | |||
92 | /* Return the current background shade */ | ||
93 | unsigned grey_get_background(void) | ||
94 | { | ||
95 | return _grey_info.bg_brightness; | ||
96 | } | ||
97 | |||
98 | /* Set draw mode, foreground and background shades at once */ | ||
99 | void grey_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) | ||
100 | { | ||
101 | grey_set_drawmode(mode); | ||
102 | grey_set_foreground(fg_brightness); | ||
103 | grey_set_background(bg_brightness); | ||
104 | } | ||
105 | |||
106 | /* Set font for the text output routines */ | ||
107 | void grey_setfont(int newfont) | ||
108 | { | ||
109 | _grey_info.curfont = newfont; | ||
110 | } | ||
111 | |||
112 | /* Get width and height of a text when printed with the current font */ | ||
113 | int grey_getstringsize(const unsigned char *str, int *w, int *h) | ||
114 | { | ||
115 | return _grey_rb->font_getstringsize(str, w, h, _grey_info.curfont); | ||
116 | } | ||
diff --git a/apps/plugins/lib/grey_scroll.c b/apps/plugins/lib/grey_scroll.c new file mode 100644 index 0000000000..80496e7706 --- /dev/null +++ b/apps/plugins/lib/grey_scroll.c | |||
@@ -0,0 +1,358 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * New greyscale framework | ||
11 | * Scrolling routines | ||
12 | * | ||
13 | * This is a generic framework to display 129 shades of grey on low-depth | ||
14 | * bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. | ||
15 | * | ||
16 | * Copyright (C) 2008 Jens Arnold | ||
17 | * | ||
18 | * All files in this archive are subject to the GNU General Public License. | ||
19 | * See the file COPYING in the source tree root for full license agreement. | ||
20 | * | ||
21 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
22 | * KIND, either express or implied. | ||
23 | * | ||
24 | ****************************************************************************/ | ||
25 | |||
26 | #include "plugin.h" | ||
27 | #include "grey.h" | ||
28 | |||
29 | /*** Scrolling ***/ | ||
30 | |||
31 | /* Scroll left */ | ||
32 | void grey_scroll_left(int count) | ||
33 | { | ||
34 | unsigned char *data, *data_end; | ||
35 | int length, blank; | ||
36 | |||
37 | if ((unsigned)count >= (unsigned)_grey_info.width) | ||
38 | return; | ||
39 | |||
40 | data = _grey_info.buffer; | ||
41 | data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); | ||
42 | length = _grey_info.width - count; | ||
43 | blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
44 | _grey_info.fg_val : _grey_info.bg_val; | ||
45 | |||
46 | do | ||
47 | { | ||
48 | _grey_rb->memmove(data, data + count, length); | ||
49 | _grey_rb->memset(data + length, blank, count); | ||
50 | data += _grey_info.width; | ||
51 | } | ||
52 | while (data < data_end); | ||
53 | } | ||
54 | |||
55 | /* Scroll right */ | ||
56 | void grey_scroll_right(int count) | ||
57 | { | ||
58 | unsigned char *data, *data_end; | ||
59 | int length, blank; | ||
60 | |||
61 | if ((unsigned)count >= (unsigned)_grey_info.width) | ||
62 | return; | ||
63 | |||
64 | data = _grey_info.buffer; | ||
65 | data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); | ||
66 | length = _grey_info.width - count; | ||
67 | blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
68 | _grey_info.fg_val : _grey_info.bg_val; | ||
69 | |||
70 | do | ||
71 | { | ||
72 | _grey_rb->memmove(data + count, data, length); | ||
73 | _grey_rb->memset(data, blank, count); | ||
74 | data += _grey_info.width; | ||
75 | } | ||
76 | while (data < data_end); | ||
77 | } | ||
78 | |||
79 | /* Scroll up */ | ||
80 | void grey_scroll_up(int count) | ||
81 | { | ||
82 | long shift, length; | ||
83 | int blank; | ||
84 | |||
85 | if ((unsigned)count >= (unsigned)_grey_info.height) | ||
86 | return; | ||
87 | |||
88 | shift = _GREY_MULUQ(_grey_info.width, count); | ||
89 | length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count); | ||
90 | blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
91 | _grey_info.fg_val : _grey_info.bg_val; | ||
92 | |||
93 | _grey_rb->memmove(_grey_info.buffer, _grey_info.buffer + shift, length); | ||
94 | _grey_rb->memset(_grey_info.buffer + length, blank, shift); | ||
95 | } | ||
96 | |||
97 | /* Scroll down */ | ||
98 | void grey_scroll_down(int count) | ||
99 | { | ||
100 | long shift, length; | ||
101 | int blank; | ||
102 | |||
103 | if ((unsigned)count >= (unsigned)_grey_info.height) | ||
104 | return; | ||
105 | |||
106 | shift = _GREY_MULUQ(_grey_info.width, count); | ||
107 | length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count); | ||
108 | blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
109 | _grey_info.fg_val : _grey_info.bg_val; | ||
110 | |||
111 | _grey_rb->memmove(_grey_info.buffer + shift, _grey_info.buffer, length); | ||
112 | _grey_rb->memset(_grey_info.buffer, blank, shift); | ||
113 | } | ||
114 | |||
115 | /*** Unbuffered scrolling functions ***/ | ||
116 | |||
117 | #ifdef SIMULATOR | ||
118 | |||
119 | /* Scroll left */ | ||
120 | void grey_ub_scroll_left(int count) | ||
121 | { | ||
122 | grey_scroll_left(count); | ||
123 | grey_update(); | ||
124 | } | ||
125 | |||
126 | /* Scroll right */ | ||
127 | void grey_ub_scroll_right(int count) | ||
128 | { | ||
129 | grey_scroll_right(count); | ||
130 | grey_update(); | ||
131 | } | ||
132 | |||
133 | /* Scroll up */ | ||
134 | void grey_ub_scroll_up(int count) | ||
135 | { | ||
136 | grey_scroll_up(count); | ||
137 | grey_update(); | ||
138 | } | ||
139 | |||
140 | /* Scroll down */ | ||
141 | void grey_ub_scroll_down(int count) | ||
142 | { | ||
143 | grey_scroll_down(count); | ||
144 | grey_update(); | ||
145 | } | ||
146 | |||
147 | #else /* !SIMULATOR */ | ||
148 | |||
149 | /* Scroll left */ | ||
150 | void grey_ub_scroll_left(int count) | ||
151 | { | ||
152 | unsigned char *dst, *src, *end; | ||
153 | int blank, y, idx; | ||
154 | |||
155 | if ((count == 0) || ((unsigned)count >= (unsigned)_grey_info.width)) | ||
156 | return; | ||
157 | |||
158 | blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
159 | _grey_info.fg_val : _grey_info.bg_val; | ||
160 | |||
161 | for (y = 0; y < _grey_info.height; y++) | ||
162 | { | ||
163 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
164 | idx = _GREY_MULUQ(_grey_info.width, y); | ||
165 | #else | ||
166 | #if LCD_DEPTH == 1 | ||
167 | idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (~y & 7); | ||
168 | #elif LCD_DEPTH == 2 | ||
169 | idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3); | ||
170 | #endif | ||
171 | #endif /* LCD_PIXELFORMAT */ | ||
172 | dst = &_grey_info.data[idx].value; | ||
173 | src = dst + count * _GREY_X_ADVANCE; | ||
174 | end = dst + _grey_info.width * _GREY_X_ADVANCE; | ||
175 | |||
176 | do | ||
177 | { | ||
178 | *dst = *src; | ||
179 | dst += _GREY_X_ADVANCE; | ||
180 | src += _GREY_X_ADVANCE; | ||
181 | } | ||
182 | while (src < end); | ||
183 | |||
184 | do | ||
185 | { | ||
186 | *dst = blank; | ||
187 | dst += _GREY_X_ADVANCE; | ||
188 | } | ||
189 | while (dst < end); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | /* Scroll right */ | ||
194 | void grey_ub_scroll_right(int count) | ||
195 | { | ||
196 | unsigned char *dst, *src, *start; | ||
197 | int blank, y, idx; | ||
198 | |||
199 | if ((count == 0) || ((unsigned)count >= (unsigned)_grey_info.width)) | ||
200 | return; | ||
201 | |||
202 | blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
203 | _grey_info.fg_val : _grey_info.bg_val; | ||
204 | |||
205 | for (y = 0; y < _grey_info.height; y++) | ||
206 | { | ||
207 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
208 | idx = _GREY_MULUQ(_grey_info.width, y); | ||
209 | #else | ||
210 | #if LCD_DEPTH == 1 | ||
211 | idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (~y & 7); | ||
212 | #elif LCD_DEPTH == 2 | ||
213 | idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3); | ||
214 | #endif | ||
215 | #endif /* LCD_PIXELFORMAT */ | ||
216 | start = &_grey_info.data[idx].value; | ||
217 | dst = start + _grey_info.width * _GREY_X_ADVANCE; | ||
218 | src = dst - count * _GREY_X_ADVANCE; | ||
219 | |||
220 | do | ||
221 | { | ||
222 | dst -= _GREY_X_ADVANCE; | ||
223 | src -= _GREY_X_ADVANCE; | ||
224 | *dst = *src; | ||
225 | } | ||
226 | while (src > start); | ||
227 | |||
228 | do | ||
229 | { | ||
230 | dst -= _GREY_X_ADVANCE; | ||
231 | *dst = blank; | ||
232 | } | ||
233 | while (dst > start); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | void grey_ub_scroll_up(int count) | ||
238 | { | ||
239 | unsigned char *dst, *dst_end, *src; | ||
240 | int blank, ys, yd, is, id; | ||
241 | |||
242 | if ((unsigned)count >= (unsigned)_grey_info.height) | ||
243 | return; | ||
244 | |||
245 | blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
246 | _grey_info.fg_val : _grey_info.bg_val; | ||
247 | |||
248 | for (ys = count, yd = 0; ys < _grey_info.height; ys++, yd++) | ||
249 | { | ||
250 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
251 | id = _GREY_MULUQ(_grey_info.width, yd); | ||
252 | is = _GREY_MULUQ(_grey_info.width, ys); | ||
253 | #else | ||
254 | #if LCD_DEPTH == 1 | ||
255 | id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7); | ||
256 | is = _GREY_MULUQ(_grey_info.width, ys & ~7) + (~ys & 7); | ||
257 | #elif LCD_DEPTH == 2 | ||
258 | id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); | ||
259 | is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3); | ||
260 | #endif | ||
261 | #endif /* LCD_PIXELFORMAT */ | ||
262 | dst = &_grey_info.data[id].value; | ||
263 | src = &_grey_info.data[is].value; | ||
264 | dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; | ||
265 | |||
266 | do | ||
267 | { | ||
268 | *dst = *src; | ||
269 | dst += _GREY_X_ADVANCE; | ||
270 | src += _GREY_X_ADVANCE; | ||
271 | } | ||
272 | while (dst < dst_end); | ||
273 | } | ||
274 | for (; yd < _grey_info.height; yd++) | ||
275 | { | ||
276 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
277 | id = _GREY_MULUQ(_grey_info.width, yd); | ||
278 | #else | ||
279 | #if LCD_DEPTH == 1 | ||
280 | id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7); | ||
281 | #elif LCD_DEPTH == 2 | ||
282 | id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); | ||
283 | #endif | ||
284 | #endif /* LCD_PIXELFORMAT */ | ||
285 | dst = &_grey_info.data[id].value; | ||
286 | dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; | ||
287 | |||
288 | do | ||
289 | { | ||
290 | *dst = blank; | ||
291 | dst += _GREY_X_ADVANCE; | ||
292 | } | ||
293 | while (dst < dst_end); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | void grey_ub_scroll_down(int count) | ||
298 | { | ||
299 | unsigned char *dst, *dst_end, *src; | ||
300 | int blank, ys, yd, is, id; | ||
301 | |||
302 | if ((unsigned)count >= (unsigned)_grey_info.height) | ||
303 | return; | ||
304 | |||
305 | blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? | ||
306 | _grey_info.fg_val : _grey_info.bg_val; | ||
307 | |||
308 | yd = _grey_info.height - 1; | ||
309 | for (ys = yd - count; ys >= 0; ys--, yd--) | ||
310 | { | ||
311 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
312 | id = _GREY_MULUQ(_grey_info.width, yd); | ||
313 | is = _GREY_MULUQ(_grey_info.width, ys); | ||
314 | #else | ||
315 | #if LCD_DEPTH == 1 | ||
316 | id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7); | ||
317 | is = _GREY_MULUQ(_grey_info.width, ys & ~7) + (~ys & 7); | ||
318 | #elif LCD_DEPTH == 2 | ||
319 | id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); | ||
320 | is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3); | ||
321 | #endif | ||
322 | #endif /* LCD_PIXELFORMAT */ | ||
323 | dst = &_grey_info.data[id].value; | ||
324 | src = &_grey_info.data[is].value; | ||
325 | dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; | ||
326 | |||
327 | do | ||
328 | { | ||
329 | *dst = *src; | ||
330 | dst += _GREY_X_ADVANCE; | ||
331 | src += _GREY_X_ADVANCE; | ||
332 | } | ||
333 | while (dst < dst_end); | ||
334 | } | ||
335 | for (; yd >= 0; yd--) | ||
336 | { | ||
337 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
338 | id = _GREY_MULUQ(_grey_info.width, yd); | ||
339 | #else | ||
340 | #if LCD_DEPTH == 1 | ||
341 | id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7); | ||
342 | #elif LCD_DEPTH == 2 | ||
343 | id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); | ||
344 | #endif | ||
345 | #endif /* LCD_PIXELFORMAT */ | ||
346 | dst = &_grey_info.data[id].value; | ||
347 | dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; | ||
348 | |||
349 | do | ||
350 | { | ||
351 | *dst = blank; | ||
352 | dst += _GREY_X_ADVANCE; | ||
353 | } | ||
354 | while (dst < dst_end); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | #endif /* !SIMULATOR */ | ||