Cube: Keep main colours and backdrop.
[Rockbox.git] / apps / plugins / cube.c
blob00c9a3b606e942787a662855e01b8ea510c275ee
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Damien Teney
11 * modified to use int instead of float math by Andreas Zwirtes
12 * heavily extended by Jens Arnold
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ***************************************************************************/
21 #include "plugin.h"
22 #include "gray.h"
23 #include "playergfx.h"
24 #include "xlcd.h"
26 PLUGIN_HEADER
28 /* Loops that the values are displayed */
29 #define DISP_TIME 30
31 /* variable button definitions */
32 #if CONFIG_KEYPAD == RECORDER_PAD
33 #define CUBE_QUIT BUTTON_OFF
34 #define CUBE_X_INC BUTTON_RIGHT
35 #define CUBE_X_DEC BUTTON_LEFT
36 #define CUBE_Y_INC BUTTON_UP
37 #define CUBE_Y_DEC BUTTON_DOWN
38 #define CUBE_Z_INC BUTTON_F2
39 #define CUBE_Z_DEC BUTTON_F1
40 #define CUBE_MODE BUTTON_F3
41 #define CUBE_PAUSE BUTTON_PLAY
42 #define CUBE_HIGHSPEED BUTTON_ON
44 #elif CONFIG_KEYPAD == PLAYER_PAD
45 #define CUBE_QUIT BUTTON_STOP
46 #define CUBE_X_INC BUTTON_RIGHT
47 #define CUBE_X_DEC BUTTON_LEFT
48 #define CUBE_Y_INC (BUTTON_ON | BUTTON_RIGHT)
49 #define CUBE_Y_DEC (BUTTON_ON | BUTTON_LEFT)
50 #define CUBE_Z_INC (BUTTON_MENU | BUTTON_RIGHT)
51 #define CUBE_Z_DEC (BUTTON_MENU | BUTTON_LEFT)
52 #define CUBE_MODE_PRE BUTTON_MENU
53 #define CUBE_MODE (BUTTON_MENU | BUTTON_REL)
54 #define CUBE_PAUSE BUTTON_PLAY
55 #define CUBE_HIGHSPEED_PRE BUTTON_ON
56 #define CUBE_HIGHSPEED (BUTTON_ON | BUTTON_REL)
58 #elif CONFIG_KEYPAD == ONDIO_PAD
59 #define CUBE_QUIT BUTTON_OFF
60 #define CUBE_X_INC BUTTON_RIGHT
61 #define CUBE_X_DEC BUTTON_LEFT
62 #define CUBE_Y_INC BUTTON_UP
63 #define CUBE_Y_DEC BUTTON_DOWN
64 #define CUBE_Z_INC (BUTTON_MENU | BUTTON_UP)
65 #define CUBE_Z_DEC (BUTTON_MENU | BUTTON_DOWN)
66 #define CUBE_MODE_PRE BUTTON_MENU
67 #define CUBE_MODE (BUTTON_MENU | BUTTON_REL)
68 #define CUBE_PAUSE (BUTTON_MENU | BUTTON_LEFT)
69 #define CUBE_HIGHSPEED (BUTTON_MENU | BUTTON_RIGHT)
71 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
72 (CONFIG_KEYPAD == IRIVER_H300_PAD)
73 #define CUBE_QUIT BUTTON_OFF
74 #define CUBE_X_INC BUTTON_RIGHT
75 #define CUBE_X_DEC BUTTON_LEFT
76 #define CUBE_Y_INC BUTTON_UP
77 #define CUBE_Y_DEC BUTTON_DOWN
78 #define CUBE_Z_INC (BUTTON_ON | BUTTON_UP)
79 #define CUBE_Z_DEC (BUTTON_ON | BUTTON_DOWN)
80 #define CUBE_MODE BUTTON_MODE
81 #define CUBE_PAUSE_PRE BUTTON_ON
82 #define CUBE_PAUSE (BUTTON_ON | BUTTON_REL)
83 #define CUBE_HIGHSPEED BUTTON_SELECT
85 #define CUBE_RC_QUIT BUTTON_RC_STOP
86 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
87 (CONFIG_KEYPAD == IPOD_3G_PAD)
88 #define CUBE_QUIT BUTTON_MENU
89 #define CUBE_X_INC BUTTON_RIGHT
90 #define CUBE_X_DEC BUTTON_LEFT
91 #define CUBE_Y_INC BUTTON_SCROLL_FWD
92 #define CUBE_Y_DEC BUTTON_SCROLL_BACK
93 #define CUBE_Z_INC (BUTTON_SELECT | BUTTON_RIGHT)
94 #define CUBE_Z_DEC (BUTTON_SELECT | BUTTON_LEFT)
95 #define CUBE_MODE (BUTTON_SELECT | BUTTON_MENU)
96 #define CUBE_PAUSE_PRE BUTTON_PLAY
97 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
98 #define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_PLAY)
100 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
101 #define CUBE_QUIT BUTTON_PLAY
102 #define CUBE_X_INC BUTTON_RIGHT
103 #define CUBE_X_DEC BUTTON_LEFT
104 #define CUBE_Y_INC BUTTON_UP
105 #define CUBE_Y_DEC BUTTON_DOWN
106 #define CUBE_Z_INC BUTTON_MODE
107 #define CUBE_Z_DEC BUTTON_EQ
108 #define CUBE_MODE (BUTTON_SELECT | BUTTON_REPEAT)
109 #define CUBE_PAUSE (BUTTON_SELECT | BUTTON_REL)
110 #define CUBE_HIGHSPEED (BUTTON_MODE | BUTTON_EQ) /* TODO: this is impossible */
112 #elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
113 #define CUBE_QUIT BUTTON_POWER
114 #define CUBE_X_INC BUTTON_LEFT
115 #define CUBE_X_DEC BUTTON_RIGHT
116 #define CUBE_Y_INC BUTTON_UP
117 #define CUBE_Y_DEC BUTTON_DOWN
118 #define CUBE_Z_INC (BUTTON_PLAY | BUTTON_UP)
119 #define CUBE_Z_DEC (BUTTON_PLAY | BUTTON_DOWN)
120 #define CUBE_MODE BUTTON_SELECT
121 #define CUBE_PAUSE_PRE BUTTON_PLAY
122 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
123 #define CUBE_HIGHSPEED (BUTTON_REC | BUTTON_REL)
125 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
126 #define CUBE_QUIT BUTTON_A
127 #define CUBE_X_INC BUTTON_LEFT
128 #define CUBE_X_DEC BUTTON_RIGHT
129 #define CUBE_Y_INC BUTTON_UP
130 #define CUBE_Y_DEC BUTTON_DOWN
131 #define CUBE_Z_INC (BUTTON_POWER | BUTTON_UP)
132 #define CUBE_Z_DEC (BUTTON_POWER | BUTTON_DOWN)
133 #define CUBE_MODE BUTTON_MENU
134 #define CUBE_PAUSE_PRE BUTTON_SELECT
135 #define CUBE_PAUSE (BUTTON_SELECT | BUTTON_REL)
136 #define CUBE_HIGHSPEED (BUTTON_POWER | BUTTON_REL)
138 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
139 #define CUBE_QUIT BUTTON_POWER
140 #define CUBE_X_INC BUTTON_LEFT
141 #define CUBE_X_DEC BUTTON_RIGHT
142 #define CUBE_Y_INC BUTTON_SCROLL_UP
143 #define CUBE_Y_DEC BUTTON_SCROLL_DOWN
144 #define CUBE_Z_INC BUTTON_UP
145 #define CUBE_Z_DEC BUTTON_DOWN
146 #define CUBE_MODE_PRE BUTTON_SELECT
147 #define CUBE_MODE (BUTTON_SELECT|BUTTON_REPEAT)
148 #define CUBE_PAUSE_PRE BUTTON_SELECT
149 #define CUBE_PAUSE (BUTTON_SELECT|BUTTON_REL)
150 #define CUBE_HIGHSPEED BUTTON_REC
152 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
153 #define CUBE_QUIT BUTTON_POWER
154 #define CUBE_X_INC BUTTON_LEFT
155 #define CUBE_X_DEC BUTTON_RIGHT
156 #define CUBE_Y_INC BUTTON_SCROLL_UP
157 #define CUBE_Y_DEC BUTTON_SCROLL_DOWN
158 #define CUBE_Z_INC (BUTTON_PLAY | BUTTON_SCROLL_UP)
159 #define CUBE_Z_DEC (BUTTON_PLAY | BUTTON_SCROLL_DOWN)
160 #define CUBE_MODE BUTTON_REW
161 #define CUBE_PAUSE_PRE BUTTON_PLAY
162 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
163 #define CUBE_HIGHSPEED (BUTTON_FF | BUTTON_REL)
165 #endif
167 #ifdef HAVE_LCD_BITMAP
169 #define DIST (10 * MIN(LCD_HEIGHT, LCD_WIDTH) / 16)
170 static int x_off = LCD_WIDTH/2;
171 static int y_off = LCD_HEIGHT/2;
173 #if LCD_DEPTH == 1
174 #define USE_GSLIB
175 struct my_lcd {
176 void (*update)(void);
177 void (*clear_display)(void);
178 void (*drawline)(int x1, int y1, int x2, int y2);
179 void (*putsxy)(int x, int y, const unsigned char *string);
182 static struct my_lcd grayfuncs = {
183 gray_update, gray_clear_display, gray_drawline, gray_putsxy
185 static struct my_lcd lcdfuncs; /* initialised at runtime */
186 static struct my_lcd *mylcd = &grayfuncs;
188 #define MYLCD(fn) mylcd->fn
189 #define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) gray_filltriangle(x1, y1, x2, y2, x3, y3)
190 #define MY_SET_FOREGROUND(fg) gray_set_foreground(fg)
191 #define MY_GET_FOREGROUND() gray_get_foreground()
193 #else
194 #define MYLCD(fn) rb->lcd_ ## fn
195 #define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) xlcd_filltriangle(x1, y1, x2, y2, x3, y3)
196 #define MY_SET_FOREGROUND(fg) rb->lcd_set_foreground(fg)
197 #define MY_GET_FOREGROUND() rb->lcd_get_foreground()
198 #endif
200 #if CONFIG_LCD == LCD_SSD1815
201 #define ASPECT 320 /* = 1.25 (fixed point 24.8) */
202 #else
203 #define ASPECT 256 /* = 1.00 */
204 #endif
206 #else /* !LCD_BITMAP */
208 #define MYLCD(fn) pgfx_ ## fn
209 #define DIST 9
210 static int x_off = 10;
211 static int y_off = 7;
212 #define ASPECT 300 /* = 1.175 */
214 #endif /* !LCD_BITMAP */
216 struct point_3D {
217 long x, y, z;
220 struct point_2D {
221 long x, y;
224 struct line {
225 int start, end;
228 struct face {
229 int corner[4];
230 int line[4];
233 /* initial, unrotated cube corners */
234 static const struct point_3D sommet[8] =
236 {-DIST, -DIST, -DIST},
237 { DIST, -DIST, -DIST},
238 { DIST, DIST, -DIST},
239 {-DIST, DIST, -DIST},
240 {-DIST, -DIST, DIST},
241 { DIST, -DIST, DIST},
242 { DIST, DIST, DIST},
243 {-DIST, DIST, DIST}
246 /* The 12 lines forming the edges */
247 static const struct line lines[12] =
249 {0, 1}, {1, 2}, {2, 3}, {3, 0},
250 {4, 7}, {7, 6}, {6, 5}, {5, 4},
251 {0, 4}, {1, 5}, {2, 6}, {3, 7}
254 static bool lines_drawn[12];
256 /* The 6 faces of the cube; points are in clockwise order when viewed
257 from the outside */
258 static const struct face faces[6] =
260 {{0, 1, 2, 3}, {0, 1, 2, 3}},
261 {{4, 7, 6, 5}, {4, 5, 6, 7}},
262 {{0, 4, 5, 1}, {8, 7, 9, 0}},
263 {{2, 6, 7, 3}, {10, 5, 11, 2}},
264 {{0, 3, 7, 4}, {3, 11, 4, 8}},
265 {{1, 5, 6, 2}, {9, 6, 10, 1}}
268 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
269 static const unsigned face_colors[6] =
271 #ifdef HAVE_LCD_COLOR
272 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0),
273 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255)
274 #elif defined(USE_GSLIB)
275 GRAY_LIGHTGRAY, GRAY_LIGHTGRAY, GRAY_DARKGRAY,
276 GRAY_DARKGRAY, GRAY_BLACK, GRAY_BLACK
277 #else
278 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY,
279 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK
280 #endif
282 #endif
284 enum {
285 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
286 SOLID,
287 #endif
288 HIDDEN_LINES,
289 WIREFRAME,
290 NUM_MODES
293 static int mode = 0;
295 static struct point_3D point3D[8];
296 static struct point_2D point2D[8];
297 static long matrice[3][3];
299 static const int nb_points = 8;
300 static long z_off = 600;
302 /* Precalculated sine and cosine * 16384 (fixed point 18.14) */
303 static const short sin_table[91] =
305 0, 285, 571, 857, 1142, 1427, 1712, 1996, 2280, 2563,
306 2845, 3126, 3406, 3685, 3963, 4240, 4516, 4790, 5062, 5334,
307 5603, 5871, 6137, 6401, 6663, 6924, 7182, 7438, 7691, 7943,
308 8191, 8438, 8682, 8923, 9161, 9397, 9630, 9860, 10086, 10310,
309 10531, 10748, 10963, 11173, 11381, 11585, 11785, 11982, 12175, 12365,
310 12550, 12732, 12910, 13084, 13254, 13420, 13582, 13740, 13894, 14043,
311 14188, 14329, 14466, 14598, 14725, 14848, 14967, 15081, 15190, 15295,
312 15395, 15491, 15582, 15668, 15749, 15825, 15897, 15964, 16025, 16082,
313 16135, 16182, 16224, 16261, 16294, 16321, 16344, 16361, 16374, 16381,
314 16384
317 static struct plugin_api* rb;
319 static long sin(int val)
321 /* Speed improvement through sukzessive lookup */
322 if (val < 181)
324 if (val < 91)
326 /* phase 0-90 degree */
327 return (long)sin_table[val];
329 else
331 /* phase 91-180 degree */
332 return (long)sin_table[180-val];
335 else
337 if (val < 271)
339 /* phase 181-270 degree */
340 return -(long)sin_table[val-180];
342 else
344 /* phase 270-359 degree */
345 return -(long)sin_table[360-val];
348 return 0;
351 static long cos(int val)
353 /* Speed improvement through sukzessive lookup */
354 if (val < 181)
356 if (val < 91)
358 /* phase 0-90 degree */
359 return (long)sin_table[90-val];
361 else
363 /* phase 91-180 degree */
364 return -(long)sin_table[val-90];
367 else
369 if (val < 271)
371 /* phase 181-270 degree */
372 return -(long)sin_table[270-val];
374 else
376 /* phase 270-359 degree */
377 return (long)sin_table[val-270];
380 return 0;
384 static void cube_rotate(int xa, int ya, int za)
386 int i;
387 /* Just to prevent unnecessary lookups */
388 long sxa, cxa, sya, cya, sza, cza;
390 sxa = sin(xa);
391 cxa = cos(xa);
392 sya = sin(ya);
393 cya = cos(ya);
394 sza = sin(za);
395 cza = cos(za);
397 /* calculate overall translation matrix */
398 matrice[0][0] = (cza * cya) >> 14;
399 matrice[1][0] = (sza * cya) >> 14;
400 matrice[2][0] = -sya;
402 matrice[0][1] = (((cza * sya) >> 14) * sxa - sza * cxa) >> 14;
403 matrice[1][1] = (((sza * sya) >> 14) * sxa + cxa * cza) >> 14;
404 matrice[2][1] = (sxa * cya) >> 14;
406 matrice[0][2] = (((cza * sya) >> 14) * cxa + sza * sxa) >> 14;
407 matrice[1][2] = (((sza * sya) >> 14) * cxa - cza * sxa) >> 14;
408 matrice[2][2] = (cxa * cya) >> 14;
410 /* apply translation matrix to all points */
411 for (i = 0; i < nb_points; i++)
413 point3D[i].x = matrice[0][0] * sommet[i].x + matrice[1][0] * sommet[i].y
414 + matrice[2][0] * sommet[i].z;
416 point3D[i].y = matrice[0][1] * sommet[i].x + matrice[1][1] * sommet[i].y
417 + matrice[2][1] * sommet[i].z;
419 point3D[i].z = matrice[0][2] * sommet[i].x + matrice[1][2] * sommet[i].y
420 + matrice[2][2] * sommet[i].z;
424 static void cube_viewport(void)
426 int i;
428 /* Do viewport transformation for all points */
429 for (i = 0; i < nb_points; i++)
431 #if ASPECT != 256
432 point2D[i].x = (point3D[i].x * ASPECT) / (point3D[i].z + (z_off << 14))
433 + x_off;
434 #else
435 point2D[i].x = (point3D[i].x << 8) / (point3D[i].z + (z_off << 14))
436 + x_off;
437 #endif
438 point2D[i].y = (point3D[i].y << 8) / (point3D[i].z + (z_off << 14))
439 + y_off;
443 static void cube_draw(void)
445 int i, j, line;
446 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
447 unsigned old_foreground;
448 #endif
450 switch (mode)
452 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
453 case SOLID:
455 old_foreground = MY_GET_FOREGROUND();
456 for (i = 0; i < 6; i++)
458 /* backface culling; if the shape winds counter-clockwise, we are
459 * looking at the backface, and the (simplified) cross product
460 * is < 0. Do not draw it. */
461 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
462 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
463 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
464 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
465 continue;
467 MY_SET_FOREGROUND(face_colors[i]);
468 MY_FILLTRIANGLE(point2D[faces[i].corner[0]].x,
469 point2D[faces[i].corner[0]].y,
470 point2D[faces[i].corner[1]].x,
471 point2D[faces[i].corner[1]].y,
472 point2D[faces[i].corner[2]].x,
473 point2D[faces[i].corner[2]].y);
474 MY_FILLTRIANGLE(point2D[faces[i].corner[0]].x,
475 point2D[faces[i].corner[0]].y,
476 point2D[faces[i].corner[2]].x,
477 point2D[faces[i].corner[2]].y,
478 point2D[faces[i].corner[3]].x,
479 point2D[faces[i].corner[3]].y);
482 MY_SET_FOREGROUND(old_foreground);
483 break;
484 #endif /* (LCD_DEPTH > 1) || GSLIB */
486 case HIDDEN_LINES:
488 rb->memset(lines_drawn, 0, sizeof(lines_drawn));
489 for (i = 0; i < 6; i++)
491 /* backface culling; if the shape winds counter-clockwise, we are
492 * looking at the backface, and the (simplified) cross product
493 * is < 0. Do not draw it. */
494 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
495 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
496 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
497 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
498 continue;
500 for (j = 0; j < 4; j++)
502 line = faces[i].line[j];
503 if (!lines_drawn[line])
505 lines_drawn[line] = true;
506 MYLCD(drawline)(point2D[lines[line].start].x,
507 point2D[lines[line].start].y,
508 point2D[lines[line].end].x,
509 point2D[lines[line].end].y);
513 break;
515 case WIREFRAME:
517 for (i = 0; i < 12; i++)
518 MYLCD(drawline)(point2D[lines[i].start].x,
519 point2D[lines[i].start].y,
520 point2D[lines[i].end].x,
521 point2D[lines[i].end].y);
522 break;
526 void cleanup(void *parameter)
528 (void)parameter;
530 #ifdef USE_GSLIB
531 gray_release();
532 #elif defined HAVE_LCD_CHARCELLS
533 pgfx_release();
534 #endif
537 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
539 char buffer[30];
540 int t_disp = 0;
541 #ifdef USE_GSLIB
542 unsigned char *gbuf;
543 unsigned int gbuf_size = 0;
544 bool mode_switch = true;
545 #endif
547 int button;
548 int lastbutton = BUTTON_NONE;
549 int xa = 0;
550 int ya = 0;
551 int za = 0;
552 int xs = 1;
553 int ys = 3;
554 int zs = 1;
555 bool highspeed = false;
556 bool paused = false;
557 bool redraw = true;
558 bool exit = false;
560 (void)(parameter);
561 rb = api;
563 #ifdef HAVE_LCD_BITMAP
564 #if LCD_DEPTH > 1
565 xlcd_init(rb);
566 #elif defined(USE_GSLIB)
567 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size);
568 if (gray_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, LCD_HEIGHT, 3, 0, NULL)
569 != 3)
571 rb->splash(HZ, true, "Couldn't get grayscale buffer");
572 return PLUGIN_ERROR;
574 /* init lcd_ function pointers */
575 lcdfuncs.update = rb->lcd_update;
576 lcdfuncs.clear_display = rb->lcd_clear_display;
577 lcdfuncs.drawline = rb->lcd_drawline;
578 lcdfuncs.putsxy = rb->lcd_putsxy;
580 gray_setfont(FONT_SYSFIXED);
581 #endif
582 rb->lcd_setfont(FONT_SYSFIXED);
583 #else /* LCD_CHARCELLS */
584 if (!pgfx_init(rb, 4, 2))
586 rb->splash(HZ*2, true, "Old LCD :(");
587 return PLUGIN_OK;
589 pgfx_display(3, 0);
590 #endif
592 while(!exit)
594 if (highspeed)
595 rb->yield();
596 else
597 rb->sleep(4);
599 if (redraw)
601 MYLCD(clear_display)();
602 cube_rotate(xa, ya, za);
603 cube_viewport();
604 cube_draw();
605 redraw = false;
608 #ifdef HAVE_LCD_BITMAP
609 if (t_disp > 0)
611 t_disp--;
612 rb->snprintf(buffer, sizeof(buffer), "x:%d y:%d z:%d h:%d",
613 xs, ys, zs, highspeed);
614 MYLCD(putsxy)(0, LCD_HEIGHT-8, buffer);
615 if (t_disp == 0)
616 redraw = true;
618 #else
619 if (t_disp > 0)
621 if (t_disp == DISP_TIME)
623 rb->snprintf(buffer, sizeof(buffer), "x%d", xs);
624 rb->lcd_puts(0, 0, buffer);
625 rb->snprintf(buffer, sizeof(buffer), "y%d", ys);
626 rb->lcd_puts(0, 1, buffer);
627 pgfx_display(3, 0);
628 rb->snprintf(buffer, sizeof(buffer), "z%d", zs);
629 rb->lcd_puts(8, 0, buffer);
630 rb->snprintf(buffer, sizeof(buffer), "h%d", highspeed);
631 rb->lcd_puts(8, 1, buffer);
633 t_disp--;
634 if (t_disp == 0)
636 rb->lcd_clear_display();
637 pgfx_display(3, 0);
640 #endif
641 #ifdef USE_GSLIB
642 if (mode_switch)
644 gray_show(mode == SOLID);
645 mode_switch = false;
647 #endif
648 MYLCD(update)();
650 if (!paused)
652 xa += xs;
653 if (xa > 359)
654 xa -= 360;
655 else if (xa < 0)
656 xa += 360;
658 ya += ys;
659 if (ya > 359)
660 ya -= 360;
661 else if (ya < 0)
662 ya += 360;
664 za += zs;
665 if (za > 359)
666 za -= 360;
667 else if (za < 0)
668 za += 360;
669 redraw = true;
672 button = rb->button_get(false);
673 switch (button)
675 case CUBE_X_INC:
676 case (CUBE_X_INC|BUTTON_REPEAT):
677 if( !paused )
679 if( xs < 10)
680 xs++;
682 else
684 xa++;
685 if( xa > 359 )
686 xa -= 360;
688 t_disp = DISP_TIME;
689 redraw = true;
690 break;
692 case CUBE_X_DEC:
693 case (CUBE_X_DEC|BUTTON_REPEAT):
694 if( !paused )
696 if (xs > -10)
697 xs--;
699 else
701 xa--;
702 if( xa < 0 )
703 xa += 360;
705 t_disp = DISP_TIME;
706 redraw = true;
707 break;
709 case CUBE_Y_INC:
710 case (CUBE_Y_INC|BUTTON_REPEAT):
711 if( !paused )
713 if (ys < 10)
714 ys++;
716 else
718 ya++;
719 if( ya > 359 )
720 ya -= 360;
722 t_disp = DISP_TIME;
723 redraw = true;
724 break;
726 case CUBE_Y_DEC:
727 case (CUBE_Y_DEC|BUTTON_REPEAT):
728 if( !paused )
730 if (ys > -10)
731 ys--;
733 else
735 ya--;
736 if( ya < 0 )
737 ya += 360;
739 t_disp = DISP_TIME;
740 redraw = true;
741 break;
743 case CUBE_Z_INC:
744 case (CUBE_Z_INC|BUTTON_REPEAT):
745 if( !paused )
747 if (zs < 10)
748 zs++;
750 else
752 za++;
753 if( za > 359 )
754 za -= 360;
756 t_disp = DISP_TIME;
757 redraw = true;
758 break;
760 case CUBE_Z_DEC:
761 case (CUBE_Z_DEC|BUTTON_REPEAT):
762 if( !paused )
764 if (zs > -10)
765 zs--;
767 else
769 za--;
770 if( za < 0 )
771 za += 360;
773 t_disp = DISP_TIME;
774 redraw = true;
775 break;
777 case CUBE_MODE:
778 #ifdef CUBE_MODE_PRE
779 if (lastbutton != CUBE_MODE_PRE)
780 break;
781 #endif
782 if (++mode >= NUM_MODES)
783 mode = 0;
784 #ifdef USE_GSLIB
785 mylcd = (mode == SOLID) ? &grayfuncs : &lcdfuncs;
786 mode_switch = true;
787 #endif
788 redraw = true;
789 break;
791 case CUBE_PAUSE:
792 #ifdef CUBE_PAUSE_PRE
793 if (lastbutton != CUBE_PAUSE_PRE)
794 break;
795 #endif
796 paused = !paused;
797 break;
799 case CUBE_HIGHSPEED:
800 #ifdef CUBE_HIGHSPEED_PRE
801 if (lastbutton != CUBE_HIGHSPEED_PRE)
802 break;
803 #endif
804 highspeed = !highspeed;
805 t_disp = DISP_TIME;
806 break;
808 #ifdef CUBE_RC_QUIT
809 case CUBE_RC_QUIT:
810 #endif
811 case CUBE_QUIT:
812 exit = true;
813 break;
815 default:
816 if (rb->default_event_handler_ex(button, cleanup, NULL)
817 == SYS_USB_CONNECTED)
818 return PLUGIN_USB_CONNECTED;
819 break;
821 if (button != BUTTON_NONE)
822 lastbutton = button;
825 #ifdef USE_GSLIB
826 gray_release();
827 #elif defined(HAVE_LCD_CHARCELLS)
828 pgfx_release();
829 #endif
830 return PLUGIN_OK;