diff options
Diffstat (limited to 'apps/plugins/lib/gray_scroll.c')
-rw-r--r-- | apps/plugins/lib/gray_scroll.c | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/apps/plugins/lib/gray_scroll.c b/apps/plugins/lib/gray_scroll.c new file mode 100644 index 0000000000..e4520e7649 --- /dev/null +++ b/apps/plugins/lib/gray_scroll.c | |||
@@ -0,0 +1,479 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Greyscale framework | ||
11 | * Scrolling routines | ||
12 | * | ||
13 | * This is a generic framework to use grayscale display within Rockbox | ||
14 | * plugins. It obviously does not work for the player. | ||
15 | * | ||
16 | * Copyright (C) 2004-2005 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 | #ifndef SIMULATOR /* not for simulator by now */ | ||
27 | #include "plugin.h" | ||
28 | |||
29 | #ifdef HAVE_LCD_BITMAP /* and also not for the Player */ | ||
30 | #include "gray.h" | ||
31 | |||
32 | /* FIXME: intermediate solution until we have properly optimised memmove() */ | ||
33 | static void *my_memmove(void *dst0, const void *src0, size_t len0) | ||
34 | { | ||
35 | char *dst = (char *) dst0; | ||
36 | char *src = (char *) src0; | ||
37 | |||
38 | if (dst <= src) | ||
39 | { | ||
40 | while (len0--) | ||
41 | *dst++ = *src++; | ||
42 | } | ||
43 | else | ||
44 | { | ||
45 | dst += len0; | ||
46 | src += len0; | ||
47 | |||
48 | while (len0--) | ||
49 | *(--dst) = *(--src); | ||
50 | } | ||
51 | |||
52 | return dst0; | ||
53 | } | ||
54 | |||
55 | /*** Scrolling ***/ | ||
56 | |||
57 | /* Scroll left */ | ||
58 | void gray_scroll_left(int count) | ||
59 | { | ||
60 | long shift, length; | ||
61 | int blank; | ||
62 | |||
63 | if ((unsigned)count >= (unsigned)_gray_info.width) | ||
64 | return; | ||
65 | |||
66 | shift = MULU16(_gray_info.height, count); | ||
67 | length = MULU16(_gray_info.height, _gray_info.width - count); | ||
68 | blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? | ||
69 | _gray_info.fg_brightness : _gray_info.bg_brightness; | ||
70 | |||
71 | my_memmove(_gray_info.cur_buffer, _gray_info.cur_buffer + shift, length); | ||
72 | _gray_rb->memset(_gray_info.cur_buffer + length, blank, shift); | ||
73 | } | ||
74 | |||
75 | /* Scroll right */ | ||
76 | void gray_scroll_right(int count) | ||
77 | { | ||
78 | long shift, length; | ||
79 | int blank; | ||
80 | |||
81 | if ((unsigned)count >= (unsigned)_gray_info.width) | ||
82 | return; | ||
83 | |||
84 | shift = MULU16(_gray_info.height, count); | ||
85 | length = MULU16(_gray_info.height, _gray_info.width - count); | ||
86 | blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? | ||
87 | _gray_info.fg_brightness : _gray_info.bg_brightness; | ||
88 | |||
89 | my_memmove(_gray_info.cur_buffer + shift, _gray_info.cur_buffer, length); | ||
90 | _gray_rb->memset(_gray_info.cur_buffer, blank, shift); | ||
91 | } | ||
92 | |||
93 | /* Scroll up */ | ||
94 | void gray_scroll_up(int count) | ||
95 | { | ||
96 | unsigned char *data, *data_end; | ||
97 | int length, blank; | ||
98 | |||
99 | if ((unsigned)count >= (unsigned)_gray_info.height) | ||
100 | return; | ||
101 | |||
102 | data = _gray_info.cur_buffer; | ||
103 | data_end = data + MULU16(_gray_info.width, _gray_info.height); | ||
104 | length = _gray_info.height - count; | ||
105 | blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? | ||
106 | _gray_info.fg_brightness : _gray_info.bg_brightness; | ||
107 | |||
108 | do | ||
109 | { | ||
110 | my_memmove(data, data + count, length); | ||
111 | _gray_rb->memset(data + length, blank, count); | ||
112 | data += _gray_info.height; | ||
113 | } | ||
114 | while (data < data_end); | ||
115 | } | ||
116 | |||
117 | /* Scroll down */ | ||
118 | void gray_scroll_down(int count) | ||
119 | { | ||
120 | unsigned char *data, *data_end; | ||
121 | int length, blank; | ||
122 | |||
123 | if ((unsigned)count >= (unsigned)_gray_info.height) | ||
124 | return; | ||
125 | |||
126 | data = _gray_info.cur_buffer; | ||
127 | data_end = data + MULU16(_gray_info.width, _gray_info.height); | ||
128 | length = _gray_info.height - count; | ||
129 | blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? | ||
130 | _gray_info.fg_brightness : _gray_info.bg_brightness; | ||
131 | |||
132 | do | ||
133 | { | ||
134 | my_memmove(data + count, data, length); | ||
135 | _gray_rb->memset(data, blank, count); | ||
136 | data += _gray_info.height; | ||
137 | } | ||
138 | while (data < data_end); | ||
139 | } | ||
140 | |||
141 | /*** Unbuffered scrolling functions ***/ | ||
142 | |||
143 | /* Scroll left */ | ||
144 | void gray_ub_scroll_left(int count) | ||
145 | { | ||
146 | int length; | ||
147 | unsigned char *ptr, *ptr_end; | ||
148 | |||
149 | if ((unsigned) count >= (unsigned) _gray_info.width) | ||
150 | return; | ||
151 | |||
152 | length = _gray_info.width - count; | ||
153 | ptr = _gray_info.plane_data; | ||
154 | ptr_end = ptr + _gray_info.plane_size; | ||
155 | |||
156 | /* Scroll row by row to minimize flicker (pixel block rows) */ | ||
157 | do | ||
158 | { | ||
159 | unsigned char *ptr_row = ptr; | ||
160 | unsigned char *row_end = ptr_row | ||
161 | + MULU16(_gray_info.plane_size, _gray_info.depth); | ||
162 | do | ||
163 | { | ||
164 | my_memmove(ptr_row, ptr_row + count, length); | ||
165 | _gray_rb->memset(ptr_row + length, 0, count); | ||
166 | ptr_row += _gray_info.plane_size; | ||
167 | } | ||
168 | while (ptr_row < row_end); | ||
169 | |||
170 | ptr += _gray_info.width; | ||
171 | } | ||
172 | while (ptr < ptr_end); | ||
173 | } | ||
174 | |||
175 | /* Scroll right */ | ||
176 | void gray_ub_scroll_right(int count) | ||
177 | { | ||
178 | int length; | ||
179 | unsigned char *ptr, *ptr_end; | ||
180 | |||
181 | if ((unsigned) count >= (unsigned) _gray_info.width) | ||
182 | return; | ||
183 | |||
184 | length = _gray_info.width - count; | ||
185 | ptr = _gray_info.plane_data; | ||
186 | ptr_end = ptr + _gray_info.plane_size; | ||
187 | |||
188 | /* Scroll row by row to minimize flicker (pixel block rows) */ | ||
189 | do | ||
190 | { | ||
191 | unsigned char *ptr_row = ptr; | ||
192 | unsigned char *row_end = ptr_row | ||
193 | + MULU16(_gray_info.plane_size, _gray_info.depth); | ||
194 | do | ||
195 | { | ||
196 | my_memmove(ptr_row + count, ptr_row, length); | ||
197 | _gray_rb->memset(ptr_row, 0, count); | ||
198 | ptr_row += _gray_info.plane_size; | ||
199 | } | ||
200 | while (ptr_row < row_end); | ||
201 | |||
202 | ptr += _gray_info.width; | ||
203 | } | ||
204 | while (ptr < ptr_end); | ||
205 | } | ||
206 | |||
207 | /* Scroll up */ | ||
208 | void gray_ub_scroll_up(int count) | ||
209 | { | ||
210 | int shift; | ||
211 | long blockshift = 0; | ||
212 | unsigned char *ptr, *ptr_end1, *ptr_end2; | ||
213 | |||
214 | if ((unsigned) count >= (unsigned) _gray_info.height) | ||
215 | return; | ||
216 | |||
217 | shift = count >> _PBLOCK_EXP; | ||
218 | count &= (_PBLOCK-1); | ||
219 | |||
220 | if (shift) | ||
221 | { | ||
222 | blockshift = MULU16(_gray_info.width, shift); | ||
223 | ptr = _gray_info.plane_data; | ||
224 | ptr_end2 = ptr + _gray_info.plane_size; | ||
225 | ptr_end1 = ptr_end2 - blockshift; | ||
226 | /* Scroll row by row to minimize flicker (pixel block rows) */ | ||
227 | do | ||
228 | { | ||
229 | unsigned char *ptr_row = ptr; | ||
230 | unsigned char *row_end = ptr_row | ||
231 | + MULU16(_gray_info.plane_size, _gray_info.depth); | ||
232 | if (ptr < ptr_end1) | ||
233 | { | ||
234 | do | ||
235 | { | ||
236 | _gray_rb->memcpy(ptr_row, ptr_row + blockshift, | ||
237 | _gray_info.width); | ||
238 | ptr_row += _gray_info.plane_size; | ||
239 | } | ||
240 | while (ptr_row < row_end); | ||
241 | } | ||
242 | else | ||
243 | { | ||
244 | do | ||
245 | { | ||
246 | _gray_rb->memset(ptr_row, 0, _gray_info.width); | ||
247 | ptr_row += _gray_info.plane_size; | ||
248 | } | ||
249 | while (ptr_row < row_end); | ||
250 | } | ||
251 | |||
252 | ptr += _gray_info.width; | ||
253 | } | ||
254 | while (ptr < ptr_end2); | ||
255 | } | ||
256 | if (count) | ||
257 | { | ||
258 | #if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1) | ||
259 | /* scroll column by column to minimize flicker */ | ||
260 | asm ( | ||
261 | "mov #0,r6 \n" /* x = 0 */ | ||
262 | "mova .su_shifttbl,r0 \n" /* calculate jump destination for */ | ||
263 | "mov.b @(r0,%5),%5 \n" /* shift amount from table */ | ||
264 | "bra .su_cloop \n" /* skip table */ | ||
265 | "add r0,%5 \n" | ||
266 | |||
267 | ".align 2 \n" | ||
268 | ".su_shifttbl: \n" /* shift jump offset table */ | ||
269 | ".byte .su_shift0 - .su_shifttbl \n" | ||
270 | ".byte .su_shift1 - .su_shifttbl \n" | ||
271 | ".byte .su_shift2 - .su_shifttbl \n" | ||
272 | ".byte .su_shift3 - .su_shifttbl \n" | ||
273 | ".byte .su_shift4 - .su_shifttbl \n" | ||
274 | ".byte .su_shift5 - .su_shifttbl \n" | ||
275 | ".byte .su_shift6 - .su_shifttbl \n" | ||
276 | ".byte .su_shift7 - .su_shifttbl \n" | ||
277 | |||
278 | ".su_cloop: \n" /* repeat for every column */ | ||
279 | "mov %1,r2 \n" /* get start address */ | ||
280 | "mov #0,r3 \n" /* current_plane = 0 */ | ||
281 | |||
282 | ".su_oloop: \n" /* repeat for every bitplane */ | ||
283 | "mov r2,r4 \n" /* get start address */ | ||
284 | "mov #0,r5 \n" /* current_row = 0 */ | ||
285 | "mov #0,r1 \n" /* fill with zero */ | ||
286 | |||
287 | ".su_iloop: \n" /* repeat for all rows */ | ||
288 | "sub %2,r4 \n" /* address -= width */ | ||
289 | "mov.b @r4,r0 \n" /* get data byte */ | ||
290 | "shll8 r1 \n" /* old data to 2nd byte */ | ||
291 | "extu.b r0,r0 \n" /* extend unsigned */ | ||
292 | "or r1,r0 \n" /* combine old data */ | ||
293 | "jmp @%5 \n" /* jump into shift "path" */ | ||
294 | "extu.b r0,r1 \n" /* store data for next round */ | ||
295 | |||
296 | ".su_shift6: \n" /* shift right by 0..7 bits */ | ||
297 | "shlr2 r0 \n" | ||
298 | ".su_shift4: \n" | ||
299 | "shlr2 r0 \n" | ||
300 | ".su_shift2: \n" | ||
301 | "bra .su_shift0 \n" | ||
302 | "shlr2 r0 \n" | ||
303 | ".su_shift7: \n" | ||
304 | "shlr2 r0 \n" | ||
305 | ".su_shift5: \n" | ||
306 | "shlr2 r0 \n" | ||
307 | ".su_shift3: \n" | ||
308 | "shlr2 r0 \n" | ||
309 | ".su_shift1: \n" | ||
310 | "shlr r0 \n" | ||
311 | ".su_shift0: \n" | ||
312 | |||
313 | "mov.b r0,@r4 \n" /* store data */ | ||
314 | "add #1,r5 \n" /* current_row++ */ | ||
315 | "cmp/hi r5,%3 \n" /* current_row < bheight - shift ? */ | ||
316 | "bt .su_iloop \n" | ||
317 | |||
318 | "add %4,r2 \n" /* start_address += plane_size */ | ||
319 | "add #1,r3 \n" /* current_plane++ */ | ||
320 | "cmp/hi r3,%0 \n" /* current_plane < depth ? */ | ||
321 | "bt .su_oloop \n" | ||
322 | |||
323 | "add #1,%1 \n" /* start_address++ */ | ||
324 | "add #1,r6 \n" /* x++ */ | ||
325 | "cmp/hi r6,%2 \n" /* x < width ? */ | ||
326 | "bt .su_cloop \n" | ||
327 | : /* outputs */ | ||
328 | : /* inputs */ | ||
329 | /* %0 */ "r"(_gray_info.depth), | ||
330 | /* %1 */ "r"(_gray_info.plane_data + _gray_info.plane_size - blockshift), | ||
331 | /* %2 */ "r"(_gray_info.width), | ||
332 | /* %3 */ "r"(_gray_info.bheight - shift), | ||
333 | /* %4 */ "r"(_gray_info.plane_size), | ||
334 | /* %5 */ "r"(count) | ||
335 | : /* clobbers */ | ||
336 | "r0", "r1", "r2", "r3", "r4", "r5", "r6" | ||
337 | ); | ||
338 | #endif | ||
339 | } | ||
340 | } | ||
341 | |||
342 | /* Scroll down */ | ||
343 | void gray_ub_scroll_down(int count) | ||
344 | { | ||
345 | int shift; | ||
346 | long blockshift = 0; | ||
347 | unsigned char *ptr, *ptr_end1, *ptr_end2; | ||
348 | |||
349 | if ((unsigned) count >= (unsigned) _gray_info.height) | ||
350 | return; | ||
351 | |||
352 | shift = count >> _PBLOCK_EXP; | ||
353 | count &= (_PBLOCK-1); | ||
354 | |||
355 | if (shift) | ||
356 | { | ||
357 | blockshift = MULU16(_gray_info.width, shift); | ||
358 | ptr_end2 = _gray_info.plane_data; | ||
359 | ptr_end1 = ptr_end2 + blockshift; | ||
360 | ptr = ptr_end2 + _gray_info.plane_size; | ||
361 | /* Scroll row by row to minimize flicker (pixel block rows) */ | ||
362 | do | ||
363 | { | ||
364 | unsigned char *ptr_row, *row_end; | ||
365 | |||
366 | ptr -= _gray_info.width; | ||
367 | ptr_row = ptr; | ||
368 | row_end = ptr_row + MULU16(_gray_info.plane_size, _gray_info.depth); | ||
369 | |||
370 | if (ptr >= ptr_end1) | ||
371 | { | ||
372 | do | ||
373 | { | ||
374 | _gray_rb->memcpy(ptr_row, ptr_row - blockshift, | ||
375 | _gray_info.width); | ||
376 | ptr_row += _gray_info.plane_size; | ||
377 | } | ||
378 | while (ptr_row < row_end); | ||
379 | } | ||
380 | else | ||
381 | { | ||
382 | do | ||
383 | { | ||
384 | _gray_rb->memset(ptr_row, 0, _gray_info.width); | ||
385 | ptr_row += _gray_info.plane_size; | ||
386 | } | ||
387 | while (ptr_row < row_end); | ||
388 | } | ||
389 | } | ||
390 | while (ptr > ptr_end2); | ||
391 | } | ||
392 | if (count) | ||
393 | { | ||
394 | #if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1) | ||
395 | /* scroll column by column to minimize flicker */ | ||
396 | asm ( | ||
397 | "mov #0,r6 \n" /* x = 0 */ | ||
398 | "mova .sd_shifttbl,r0 \n" /* calculate jump destination for */ | ||
399 | "mov.b @(r0,%5),%5 \n" /* shift amount from table */ | ||
400 | "bra .sd_cloop \n" /* skip table */ | ||
401 | "add r0,%5 \n" | ||
402 | |||
403 | ".align 2 \n" | ||
404 | ".sd_shifttbl: \n" /* shift jump offset table */ | ||
405 | ".byte .sd_shift0 - .sd_shifttbl \n" | ||
406 | ".byte .sd_shift1 - .sd_shifttbl \n" | ||
407 | ".byte .sd_shift2 - .sd_shifttbl \n" | ||
408 | ".byte .sd_shift3 - .sd_shifttbl \n" | ||
409 | ".byte .sd_shift4 - .sd_shifttbl \n" | ||
410 | ".byte .sd_shift5 - .sd_shifttbl \n" | ||
411 | ".byte .sd_shift6 - .sd_shifttbl \n" | ||
412 | ".byte .sd_shift7 - .sd_shifttbl \n" | ||
413 | |||
414 | ".sd_cloop: \n" /* repeat for every column */ | ||
415 | "mov %1,r2 \n" /* get start address */ | ||
416 | "mov #0,r3 \n" /* current_plane = 0 */ | ||
417 | |||
418 | ".sd_oloop: \n" /* repeat for every bitplane */ | ||
419 | "mov r2,r4 \n" /* get start address */ | ||
420 | "mov #0,r5 \n" /* current_row = 0 */ | ||
421 | "mov #0,r1 \n" /* fill with zero */ | ||
422 | |||
423 | ".sd_iloop: \n" /* repeat for all rows */ | ||
424 | "shlr8 r1 \n" /* shift right to get residue */ | ||
425 | "mov.b @r4,r0 \n" /* get data byte */ | ||
426 | "jmp @%5 \n" /* jump into shift "path" */ | ||
427 | "extu.b r0,r0 \n" /* extend unsigned */ | ||
428 | |||
429 | ".sd_shift6: \n" /* shift left by 0..7 bits */ | ||
430 | "shll2 r0 \n" | ||
431 | ".sd_shift4: \n" | ||
432 | "shll2 r0 \n" | ||
433 | ".sd_shift2: \n" | ||
434 | "bra .sd_shift0 \n" | ||
435 | "shll2 r0 \n" | ||
436 | ".sd_shift7: \n" | ||
437 | "shll2 r0 \n" | ||
438 | ".sd_shift5: \n" | ||
439 | "shll2 r0 \n" | ||
440 | ".sd_shift3: \n" | ||
441 | "shll2 r0 \n" | ||
442 | ".sd_shift1: \n" | ||
443 | "shll r0 \n" | ||
444 | ".sd_shift0: \n" | ||
445 | |||
446 | "or r0,r1 \n" /* combine with last residue */ | ||
447 | "mov.b r1,@r4 \n" /* store data */ | ||
448 | "add %2,r4 \n" /* address += width */ | ||
449 | "add #1,r5 \n" /* current_row++ */ | ||
450 | "cmp/hi r5,%3 \n" /* current_row < bheight - shift ? */ | ||
451 | "bt .sd_iloop \n" | ||
452 | |||
453 | "add %4,r2 \n" /* start_address += plane_size */ | ||
454 | "add #1,r3 \n" /* current_plane++ */ | ||
455 | "cmp/hi r3,%0 \n" /* current_plane < depth ? */ | ||
456 | "bt .sd_oloop \n" | ||
457 | |||
458 | "add #1,%1 \n" /* start_address++ */ | ||
459 | "add #1,r6 \n" /* x++ */ | ||
460 | "cmp/hi r6,%2 \n" /* x < width ? */ | ||
461 | "bt .sd_cloop \n" | ||
462 | : /* outputs */ | ||
463 | : /* inputs */ | ||
464 | /* %0 */ "r"(_gray_info.depth), | ||
465 | /* %1 */ "r"(_gray_info.plane_data + blockshift), | ||
466 | /* %2 */ "r"(_gray_info.width), | ||
467 | /* %3 */ "r"(_gray_info.bheight - shift), | ||
468 | /* %4 */ "r"(_gray_info.plane_size), | ||
469 | /* %5 */ "r"(count) | ||
470 | : /* clobbers */ | ||
471 | "r0", "r1", "r2", "r3", "r4", "r5", "r6" | ||
472 | ); | ||
473 | #endif | ||
474 | } | ||
475 | } | ||
476 | |||
477 | #endif /* HAVE_LCD_BITMAP */ | ||
478 | #endif /* !SIMULATOR */ | ||
479 | |||