summaryrefslogtreecommitdiff
path: root/apps/plugins/lib/gray_scroll.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lib/gray_scroll.c')
-rw-r--r--apps/plugins/lib/gray_scroll.c479
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() */
33static 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 */
58void 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 */
76void 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 */
94void 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 */
118void 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 */
144void 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 */
176void 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 */
208void 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 */
343void 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