Initial 800x480 cabbiev2 port, based on 480x800x16 one
[kugel-rb.git] / apps / plugins / cube.c
blob6d0e14f8f0675a93af44b9ff7f2106347906397e
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 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ***************************************************************************/
23 #include "plugin.h"
24 #include "lib/playergfx.h"
25 #include "lib/pluginlib_exit.h"
26 #if LCD_DEPTH > 1
27 #include "lib/mylcd.h" /* MYLCD_CFG_RB_XLCD or MYLCD_CFG_PGFX */
28 #include "lib/grey.h"
29 #else
30 #include "lib/grey.h"
31 #include "lib/mylcd.h" /* MYLCD_CFG_GREYLIB or MYLCD_CFG_PGFX */
32 #endif
33 #include "lib/xlcd.h"
34 #include "lib/fixedpoint.h"
36 /* Loops that the values are displayed */
37 #define DISP_TIME 30
39 /* variable button definitions */
40 #if CONFIG_KEYPAD == RECORDER_PAD
41 #define CUBE_QUIT BUTTON_OFF
42 #define CUBE_NEXT BUTTON_RIGHT
43 #define CUBE_PREV BUTTON_LEFT
44 #define CUBE_INC BUTTON_UP
45 #define CUBE_DEC BUTTON_DOWN
46 #define CUBE_MODE BUTTON_F1
47 #define CUBE_PAUSE BUTTON_PLAY
48 #define CUBE_HIGHSPEED BUTTON_ON
50 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
51 #define CUBE_QUIT BUTTON_OFF
52 #define CUBE_NEXT BUTTON_RIGHT
53 #define CUBE_PREV BUTTON_LEFT
54 #define CUBE_INC BUTTON_UP
55 #define CUBE_DEC BUTTON_DOWN
56 #define CUBE_MODE BUTTON_F1
57 #define CUBE_PAUSE BUTTON_SELECT
58 #define CUBE_HIGHSPEED BUTTON_ON
60 #elif CONFIG_KEYPAD == PLAYER_PAD
61 #define CUBE_QUIT BUTTON_STOP
62 #define CUBE_INC BUTTON_RIGHT
63 #define CUBE_DEC BUTTON_LEFT
64 #define CUBE_NEXT (BUTTON_ON | BUTTON_RIGHT)
65 #define CUBE_PREV (BUTTON_ON | BUTTON_LEFT)
66 #define CUBE_MODE BUTTON_MENU
67 #define CUBE_PAUSE BUTTON_PLAY
68 #define CUBE_HIGHSPEED_PRE BUTTON_ON
69 #define CUBE_HIGHSPEED (BUTTON_ON | BUTTON_REL)
71 #elif CONFIG_KEYPAD == ONDIO_PAD
72 #define CUBE_QUIT BUTTON_OFF
73 #define CUBE_NEXT BUTTON_RIGHT
74 #define CUBE_PREV BUTTON_LEFT
75 #define CUBE_INC BUTTON_UP
76 #define CUBE_DEC BUTTON_DOWN
77 #define CUBE_MODE_PRE BUTTON_MENU
78 #define CUBE_MODE (BUTTON_MENU | BUTTON_REL)
79 #define CUBE_PAUSE (BUTTON_MENU | BUTTON_LEFT)
80 #define CUBE_HIGHSPEED (BUTTON_MENU | BUTTON_RIGHT)
82 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
83 (CONFIG_KEYPAD == IRIVER_H300_PAD)
84 #define CUBE_QUIT BUTTON_OFF
85 #define CUBE_NEXT BUTTON_RIGHT
86 #define CUBE_PREV BUTTON_LEFT
87 #define CUBE_INC BUTTON_UP
88 #define CUBE_DEC BUTTON_DOWN
89 #define CUBE_MODE BUTTON_MODE
90 #define CUBE_PAUSE BUTTON_ON
91 #define CUBE_HIGHSPEED BUTTON_SELECT
93 #define CUBE_RC_QUIT BUTTON_RC_STOP
95 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
96 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
97 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
98 #define CUBE_QUIT (BUTTON_SELECT | BUTTON_MENU)
99 #define CUBE_NEXT BUTTON_RIGHT
100 #define CUBE_PREV BUTTON_LEFT
101 #define CUBE_INC BUTTON_SCROLL_FWD
102 #define CUBE_DEC BUTTON_SCROLL_BACK
103 #define CUBE_MODE BUTTON_MENU
104 #define CUBE_PAUSE BUTTON_PLAY
105 #define CUBE_HIGHSPEED_PRE BUTTON_SELECT
106 #define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_REL)
108 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
109 #define CUBE_QUIT BUTTON_PLAY
110 #define CUBE_NEXT BUTTON_RIGHT
111 #define CUBE_PREV BUTTON_LEFT
112 #define CUBE_INC BUTTON_UP
113 #define CUBE_DEC BUTTON_DOWN
114 #define CUBE_MODE BUTTON_MODE
115 #define CUBE_PAUSE BUTTON_SELECT
116 #define CUBE_HIGHSPEED BUTTON_EQ
118 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
119 #define CUBE_QUIT BUTTON_POWER
120 #define CUBE_NEXT BUTTON_RIGHT
121 #define CUBE_PREV BUTTON_LEFT
122 #define CUBE_INC BUTTON_UP
123 #define CUBE_DEC BUTTON_DOWN
124 #define CUBE_MODE BUTTON_REC
125 #define CUBE_PAUSE BUTTON_PLAY
126 #define CUBE_HIGHSPEED BUTTON_SELECT
128 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
129 #define CUBE_QUIT BUTTON_POWER
130 #define CUBE_NEXT BUTTON_RIGHT
131 #define CUBE_PREV BUTTON_LEFT
132 #define CUBE_INC BUTTON_UP
133 #define CUBE_DEC BUTTON_DOWN
134 #define CUBE_MODE BUTTON_MENU
135 #define CUBE_PAUSE BUTTON_SELECT
136 #define CUBE_HIGHSPEED BUTTON_A
138 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
139 #define CUBE_QUIT BUTTON_POWER
140 #define CUBE_NEXT BUTTON_RIGHT
141 #define CUBE_PREV BUTTON_LEFT
142 #define CUBE_INC BUTTON_SCROLL_FWD
143 #define CUBE_DEC BUTTON_SCROLL_BACK
144 #define CUBE_MODE BUTTON_DOWN
145 #define CUBE_PAUSE BUTTON_UP
146 #define CUBE_HIGHSPEED BUTTON_SELECT
148 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
149 #define CUBE_QUIT (BUTTON_HOME|BUTTON_REPEAT)
150 #define CUBE_NEXT BUTTON_RIGHT
151 #define CUBE_PREV BUTTON_LEFT
152 #define CUBE_INC BUTTON_SCROLL_FWD
153 #define CUBE_DEC BUTTON_SCROLL_BACK
154 #define CUBE_MODE BUTTON_DOWN
155 #define CUBE_PAUSE BUTTON_UP
156 #define CUBE_HIGHSPEED BUTTON_SELECT
158 #elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \
159 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
160 (CONFIG_KEYPAD == SANSA_M200_PAD)
161 #define CUBE_QUIT BUTTON_POWER
162 #define CUBE_NEXT BUTTON_RIGHT
163 #define CUBE_PREV BUTTON_LEFT
164 #define CUBE_INC BUTTON_VOL_UP
165 #define CUBE_DEC BUTTON_VOL_DOWN
166 #define CUBE_MODE BUTTON_DOWN
167 #define CUBE_PAUSE BUTTON_UP
168 #define CUBE_HIGHSPEED BUTTON_SELECT
171 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
172 #define CUBE_QUIT BUTTON_POWER
173 #define CUBE_NEXT BUTTON_RIGHT
174 #define CUBE_PREV BUTTON_LEFT
175 #define CUBE_INC BUTTON_SCROLL_UP
176 #define CUBE_DEC BUTTON_SCROLL_DOWN
177 #define CUBE_MODE BUTTON_REW
178 #define CUBE_PAUSE BUTTON_PLAY
179 #define CUBE_HIGHSPEED BUTTON_FF
181 #elif CONFIG_KEYPAD == MROBE500_PAD
182 #define CUBE_QUIT BUTTON_POWER
184 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
185 #define CUBE_QUIT BUTTON_BACK
186 #define CUBE_NEXT BUTTON_RIGHT
187 #define CUBE_PREV BUTTON_LEFT
188 #define CUBE_INC BUTTON_UP
189 #define CUBE_DEC BUTTON_DOWN
190 #define CUBE_MODE BUTTON_MENU
191 #define CUBE_PAUSE BUTTON_PLAY
192 #define CUBE_HIGHSPEED BUTTON_SELECT
194 #elif (CONFIG_KEYPAD == MROBE100_PAD)
195 #define CUBE_QUIT BUTTON_POWER
196 #define CUBE_NEXT BUTTON_RIGHT
197 #define CUBE_PREV BUTTON_LEFT
198 #define CUBE_INC BUTTON_UP
199 #define CUBE_DEC BUTTON_DOWN
200 #define CUBE_MODE BUTTON_MENU
201 #define CUBE_PAUSE BUTTON_PLAY
202 #define CUBE_HIGHSPEED BUTTON_SELECT
204 #elif (CONFIG_KEYPAD == IAUDIO_M3_PAD)
205 #define CUBE_QUIT BUTTON_RC_REC
206 #define CUBE_NEXT BUTTON_RC_FF
207 #define CUBE_PREV BUTTON_RC_REW
208 #define CUBE_INC BUTTON_RC_VOL_UP
209 #define CUBE_DEC BUTTON_RC_VOL_DOWN
210 #define CUBE_MODE BUTTON_RC_MODE
211 #define CUBE_PAUSE BUTTON_RC_PLAY
212 #define CUBE_HIGHSPEED BUTTON_RC_MENU
214 #elif CONFIG_KEYPAD == COWON_D2_PAD
215 #define CUBE_QUIT BUTTON_POWER
217 #elif (CONFIG_KEYPAD == IAUDIO67_PAD)
218 #define CUBE_QUIT BUTTON_POWER
219 #define CUBE_NEXT BUTTON_RIGHT
220 #define CUBE_PREV BUTTON_LEFT
221 #define CUBE_INC BUTTON_VOLUP
222 #define CUBE_DEC BUTTON_VOLDOWN
223 #define CUBE_MODE BUTTON_MENU
224 #define CUBE_PAUSE BUTTON_PLAY
225 #define CUBE_HIGHSPEED BUTTON_STOP
227 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
228 #define CUBE_QUIT BUTTON_BACK
229 #define CUBE_NEXT BUTTON_RIGHT
230 #define CUBE_PREV BUTTON_LEFT
231 #define CUBE_INC BUTTON_UP
232 #define CUBE_DEC BUTTON_DOWN
233 #define CUBE_MODE BUTTON_MENU
234 #define CUBE_PAUSE BUTTON_PLAY
235 #define CUBE_HIGHSPEED BUTTON_SELECT
237 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
238 #define CUBE_QUIT BUTTON_POWER
239 #define CUBE_NEXT BUTTON_RIGHT
240 #define CUBE_PREV BUTTON_LEFT
241 #define CUBE_INC BUTTON_UP
242 #define CUBE_DEC BUTTON_DOWN
243 #define CUBE_MODE BUTTON_MENU
244 #define CUBE_PAUSE BUTTON_SELECT
245 #define CUBE_HIGHSPEED BUTTON_VIEW
247 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
248 #define CUBE_QUIT BUTTON_POWER
249 #define CUBE_NEXT BUTTON_NEXT
250 #define CUBE_PREV BUTTON_PREV
251 #define CUBE_INC BUTTON_UP
252 #define CUBE_DEC BUTTON_DOWN
253 #define CUBE_MODE BUTTON_MENU
254 #define CUBE_PAUSE BUTTON_PLAY
255 #define CUBE_HIGHSPEED BUTTON_RIGHT
257 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
258 #define CUBE_QUIT BUTTON_POWER
259 #define CUBE_NEXT BUTTON_NEXT
260 #define CUBE_PREV BUTTON_PREV
261 #define CUBE_INC BUTTON_UP
262 #define CUBE_DEC BUTTON_DOWN
263 #define CUBE_MODE BUTTON_MENU
264 #define CUBE_PAUSE BUTTON_PLAY
265 #define CUBE_HIGHSPEED BUTTON_RIGHT
267 #elif CONFIG_KEYPAD == ONDAVX747_PAD
268 #define CUBE_QUIT BUTTON_POWER
269 #elif CONFIG_KEYPAD == ONDAVX777_PAD
270 #define CUBE_QUIT BUTTON_POWER
272 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
273 #define CUBE_QUIT BUTTON_REC
274 #define CUBE_NEXT BUTTON_RIGHT
275 #define CUBE_PREV BUTTON_LEFT
276 #define CUBE_INC BUTTON_UP
277 #define CUBE_DEC BUTTON_DOWN
278 #define CUBE_MODE BUTTON_REW
279 #define CUBE_PAUSE BUTTON_PLAY
280 #define CUBE_HIGHSPEED BUTTON_FFWD
282 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
283 #define CUBE_QUIT BUTTON_REC
284 #define CUBE_NEXT BUTTON_NEXT
285 #define CUBE_PREV BUTTON_PREV
286 #define CUBE_INC BUTTON_UP
287 #define CUBE_DEC BUTTON_DOWN
288 #define CUBE_MODE BUTTON_MENU
289 #define CUBE_PAUSE BUTTON_PLAY
290 #define CUBE_HIGHSPEED BUTTON_OK
292 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
293 #define CUBE_QUIT (BUTTON_REC | BUTTON_PLAY)
294 #define CUBE_NEXT BUTTON_FF
295 #define CUBE_PREV BUTTON_REW
296 #define CUBE_INC BUTTON_VOL_UP
297 #define CUBE_DEC BUTTON_VOL_DOWN
298 #define CUBE_MODE BUTTON_REC
299 #define CUBE_PAUSE BUTTON_PLAY
300 #define CUBE_HIGHSPEED BUTTON_FUNC
302 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
303 #define CUBE_QUIT BUTTON_REC
304 #define CUBE_NEXT BUTTON_FF
305 #define CUBE_PREV BUTTON_REW
306 #define CUBE_INC BUTTON_UP
307 #define CUBE_DEC BUTTON_DOWN
308 #define CUBE_MODE BUTTON_MENU
309 #define CUBE_PAUSE BUTTON_PLAY
310 #define CUBE_HIGHSPEED BUTTON_ENTER
312 #else
313 #error No keymap defined!
314 #endif
316 #ifdef HAVE_TOUCHSCREEN
317 #ifndef CUBE_QUIT
318 #define CUBE_QUIT BUTTON_TOPLEFT
319 #endif
320 #ifndef CUBE_NEXT
321 #define CUBE_NEXT BUTTON_MIDRIGHT
322 #endif
323 #ifndef CUBE_PREV
324 #define CUBE_PREV BUTTON_MIDLEFT
325 #endif
326 #ifndef CUBE_INC
327 #define CUBE_INC BUTTON_TOPMIDDLE
328 #endif
329 #ifndef CUBE_DEC
330 #define CUBE_DEC BUTTON_BOTTOMMIDDLE
331 #endif
332 #ifndef CUBE_MODE
333 #define CUBE_MODE BUTTON_TOPRIGHT
334 #endif
335 #ifndef CUBE_PAUSE
336 #define CUBE_PAUSE BUTTON_CENTER
337 #endif
338 #ifndef CUBE_HIGHSPEED
339 #define CUBE_HIGHSPEED BUTTON_BOTTOMRIGHT
340 #endif
341 #endif
344 #ifdef HAVE_LCD_BITMAP
346 #define DIST (10 * MIN(LCD_HEIGHT, LCD_WIDTH) / 16)
347 static int x_off = LCD_WIDTH/2;
348 static int y_off = LCD_HEIGHT/2;
350 #if LCD_DEPTH == 1
351 #define USEGSLIB
352 GREY_INFO_STRUCT
353 struct my_lcd {
354 void (*update)(void);
355 void (*clear_display)(void);
356 void (*drawline)(int x1, int y1, int x2, int y2);
357 void (*putsxy)(int x, int y, const unsigned char *string);
360 static struct my_lcd greyfuncs = {
361 grey_update, grey_clear_display, grey_drawline, grey_putsxy
363 static struct my_lcd lcdfuncs; /* initialised at runtime */
364 static struct my_lcd *mylcd = &greyfuncs;
366 #define MYLCD(fn) mylcd->fn
368 #else
369 #define MYLCD(fn) rb->lcd_ ## fn
370 #endif
372 #if CONFIG_LCD == LCD_SSD1815
373 #define ASPECT 320 /* = 1.25 (fixed point 24.8) */
374 #else
375 #define ASPECT 256 /* = 1.00 */
376 #endif
378 #else /* !LCD_BITMAP */
380 #define MYLCD(fn) pgfx_ ## fn
381 #define DIST 9
382 static int x_off = 10;
383 static int y_off = 7;
384 #define ASPECT 300 /* = 1.175 */
386 #endif /* !LCD_BITMAP */
388 struct point_3D {
389 long x, y, z;
392 struct point_2D {
393 long x, y;
396 struct line {
397 int start, end;
400 struct face {
401 int corner[4];
402 int line[4];
405 /* initial, unrotated cube corners */
406 static const struct point_3D sommet[8] =
408 {-DIST, -DIST, -DIST},
409 { DIST, -DIST, -DIST},
410 { DIST, DIST, -DIST},
411 {-DIST, DIST, -DIST},
412 {-DIST, -DIST, DIST},
413 { DIST, -DIST, DIST},
414 { DIST, DIST, DIST},
415 {-DIST, DIST, DIST}
418 /* The 12 lines forming the edges */
419 static const struct line lines[12] =
421 {0, 1}, {1, 2}, {2, 3}, {3, 0},
422 {4, 7}, {7, 6}, {6, 5}, {5, 4},
423 {0, 4}, {1, 5}, {2, 6}, {3, 7}
426 static bool lines_drawn[12];
428 /* The 6 faces of the cube; points are in clockwise order when viewed
429 from the outside */
430 static const struct face faces[6] =
432 {{0, 1, 2, 3}, {0, 1, 2, 3}},
433 {{4, 7, 6, 5}, {4, 5, 6, 7}},
434 {{0, 4, 5, 1}, {8, 7, 9, 0}},
435 {{2, 6, 7, 3}, {10, 5, 11, 2}},
436 {{0, 3, 7, 4}, {3, 11, 4, 8}},
437 {{1, 5, 6, 2}, {9, 6, 10, 1}}
440 #if LCD_DEPTH > 1 || defined(USEGSLIB)
441 static const unsigned face_colors[6] =
443 #ifdef HAVE_LCD_COLOR
444 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0),
445 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255)
446 #elif defined(USEGSLIB)
447 #ifdef MROBE_100
448 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
449 GREY_DARKGRAY, GREY_WHITE, GREY_WHITE
450 #else
451 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
452 GREY_DARKGRAY, GREY_BLACK, GREY_BLACK
453 #endif
454 #else
455 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY,
456 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK
457 #endif
459 #endif
461 enum {
462 #if LCD_DEPTH > 1 || defined(USEGSLIB)
463 SOLID,
464 #endif
465 HIDDEN_LINES,
466 WIREFRAME,
467 NUM_MODES
470 static int mode = 0;
472 struct counter {
473 const char *label;
474 short speed;
475 short angle;
478 static struct counter axes[] = {
479 {"x-axis", 1, 0},
480 {"y-axis", 3, 0},
481 {"z-axis", 2, 0}
484 static struct point_3D point3D[8];
485 static struct point_2D point2D[8];
486 static long matrice[3][3];
488 static const int nb_points = 8;
489 static long z_off = 600;
491 static void cube_rotate(int xa, int ya, int za)
493 int i;
494 /* Just to prevent unnecessary lookups */
495 long sxa, cxa, sya, cya, sza, cza;
497 sxa = fp14_sin(xa);
498 cxa = fp14_cos(xa);
499 sya = fp14_sin(ya);
500 cya = fp14_cos(ya);
501 sza = fp14_sin(za);
502 cza = fp14_cos(za);
504 /* calculate overall translation matrix */
505 matrice[0][0] = (cza * cya) >> 14;
506 matrice[1][0] = (sza * cya) >> 14;
507 matrice[2][0] = -sya;
509 matrice[0][1] = (((cza * sya) >> 14) * sxa - sza * cxa) >> 14;
510 matrice[1][1] = (((sza * sya) >> 14) * sxa + cxa * cza) >> 14;
511 matrice[2][1] = (sxa * cya) >> 14;
513 matrice[0][2] = (((cza * sya) >> 14) * cxa + sza * sxa) >> 14;
514 matrice[1][2] = (((sza * sya) >> 14) * cxa - cza * sxa) >> 14;
515 matrice[2][2] = (cxa * cya) >> 14;
517 /* apply translation matrix to all points */
518 for (i = 0; i < nb_points; i++)
520 point3D[i].x = matrice[0][0] * sommet[i].x + matrice[1][0] * sommet[i].y
521 + matrice[2][0] * sommet[i].z;
523 point3D[i].y = matrice[0][1] * sommet[i].x + matrice[1][1] * sommet[i].y
524 + matrice[2][1] * sommet[i].z;
526 point3D[i].z = matrice[0][2] * sommet[i].x + matrice[1][2] * sommet[i].y
527 + matrice[2][2] * sommet[i].z;
531 static void cube_viewport(void)
533 int i;
535 /* Do viewport transformation for all points */
536 for (i = 0; i < nb_points; i++)
538 #if ASPECT != 256
539 point2D[i].x = (point3D[i].x * ASPECT) / (point3D[i].z + (z_off << 14))
540 + x_off;
541 #else
542 point2D[i].x = (point3D[i].x << 8) / (point3D[i].z + (z_off << 14))
543 + x_off;
544 #endif
545 point2D[i].y = (point3D[i].y << 8) / (point3D[i].z + (z_off << 14))
546 + y_off;
550 static void cube_draw(void)
552 int i, j, line;
553 #if LCD_DEPTH > 1 || defined(USEGSLIB)
554 unsigned old_foreground;
555 #endif
557 switch (mode)
559 #if LCD_DEPTH > 1 || defined(USEGSLIB)
560 case SOLID:
562 old_foreground = mylcd_get_foreground();
563 for (i = 0; i < 6; i++)
565 /* backface culling; if the shape winds counter-clockwise, we are
566 * looking at the backface, and the (simplified) cross product
567 * is < 0. Do not draw it. */
568 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
569 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
570 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
571 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
572 continue;
574 mylcd_set_foreground(face_colors[i]);
575 mylcd_filltriangle(point2D[faces[i].corner[0]].x,
576 point2D[faces[i].corner[0]].y,
577 point2D[faces[i].corner[1]].x,
578 point2D[faces[i].corner[1]].y,
579 point2D[faces[i].corner[2]].x,
580 point2D[faces[i].corner[2]].y);
581 mylcd_filltriangle(point2D[faces[i].corner[0]].x,
582 point2D[faces[i].corner[0]].y,
583 point2D[faces[i].corner[2]].x,
584 point2D[faces[i].corner[2]].y,
585 point2D[faces[i].corner[3]].x,
586 point2D[faces[i].corner[3]].y);
589 mylcd_set_foreground(old_foreground);
590 break;
591 #endif /* (LCD_DEPTH > 1) || GSLIB */
593 case HIDDEN_LINES:
595 rb->memset(lines_drawn, 0, sizeof(lines_drawn));
596 for (i = 0; i < 6; i++)
598 /* backface culling; if the shape winds counter-clockwise, we are
599 * looking at the backface, and the (simplified) cross product
600 * is < 0. Do not draw it. */
601 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
602 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
603 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
604 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
605 continue;
607 for (j = 0; j < 4; j++)
609 line = faces[i].line[j];
610 if (!lines_drawn[line])
612 lines_drawn[line] = true;
613 MYLCD(drawline)(point2D[lines[line].start].x,
614 point2D[lines[line].start].y,
615 point2D[lines[line].end].x,
616 point2D[lines[line].end].y);
620 break;
622 case WIREFRAME:
624 for (i = 0; i < 12; i++)
625 MYLCD(drawline)(point2D[lines[i].start].x,
626 point2D[lines[i].start].y,
627 point2D[lines[i].end].x,
628 point2D[lines[i].end].y);
629 break;
633 void cleanup(void)
635 #ifdef USEGSLIB
636 grey_release();
637 #elif defined HAVE_LCD_CHARCELLS
638 pgfx_release();
639 #endif
642 enum plugin_status plugin_start(const void* parameter)
644 int t_disp = 0;
645 #ifdef USEGSLIB
646 unsigned char *gbuf;
647 size_t gbuf_size = 0;
648 bool mode_switch = true;
649 #endif
651 int button;
652 int lastbutton = BUTTON_NONE;
653 int curr = 0;
654 bool highspeed = false;
655 bool paused = false;
656 bool redraw = true;
657 bool quit = false;
659 (void)(parameter);
661 #ifdef HAVE_LCD_BITMAP
662 #if defined(USEGSLIB)
663 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size);
664 if (!grey_init(gbuf, gbuf_size, GREY_BUFFERED,
665 LCD_WIDTH, LCD_HEIGHT, NULL))
667 rb->splash(HZ, "Couldn't init greyscale display");
668 return PLUGIN_ERROR;
671 /* init lcd_ function pointers */
672 lcdfuncs.update = rb->lcd_update;
673 lcdfuncs.clear_display = rb->lcd_clear_display;
674 lcdfuncs.drawline = rb->lcd_drawline;
675 lcdfuncs.putsxy = rb->lcd_putsxy;
677 #ifdef MROBE_100
678 grey_set_background(GREY_BLACK);
679 #endif
681 grey_setfont(FONT_SYSFIXED);
682 #endif
683 rb->lcd_setfont(FONT_SYSFIXED);
684 #else /* LCD_CHARCELLS */
685 if (!pgfx_init(4, 2))
687 rb->splash(HZ*2, "Old LCD :(");
688 return PLUGIN_OK;
690 pgfx_display(0, 0);
691 #endif
693 atexit(cleanup);
694 while(!quit)
696 if (redraw)
698 MYLCD(clear_display)();
699 cube_rotate(axes[0].angle, axes[1].angle, axes[2].angle);
700 cube_viewport();
701 cube_draw();
702 redraw = false;
705 #ifdef HAVE_LCD_BITMAP
706 if (t_disp > 0)
708 char buffer[30];
709 t_disp--;
710 rb->snprintf(buffer, sizeof(buffer), "%s: %d %s",
711 axes[curr].label,
712 paused ? axes[curr].angle : axes[curr].speed,
713 highspeed ? "(hs)" : "");
714 MYLCD(putsxy)(0, LCD_HEIGHT-8, buffer);
715 if (t_disp == 0)
716 redraw = true;
718 #else
719 if (t_disp > 0)
721 if (t_disp == DISP_TIME)
723 rb->lcd_puts(5, 0, axes[curr].label);
724 rb->lcd_putsf(5, 1, "%d %c",
725 paused ? axes[curr].angle : axes[curr].speed,
726 highspeed ? 'H' : ' ');
728 t_disp--;
729 if (t_disp == 0)
731 rb->lcd_clear_display();
732 pgfx_display(0, 0);
735 #endif
736 #ifdef USEGSLIB
737 if (mode_switch)
739 grey_show(mode == SOLID);
740 mode_switch = false;
742 #endif
743 MYLCD(update)();
745 if (!paused)
747 int i;
749 for (i = 0; i < 3; i++)
751 axes[i].angle += axes[i].speed;
752 if (axes[i].angle > 359)
753 axes[i].angle -= 360;
754 else if (axes[i].angle < 0)
755 axes[i].angle += 360;
757 redraw = true;
759 if (highspeed)
760 rb->yield();
761 else
762 rb->sleep(HZ/25);
763 button = rb->button_get(false);
765 else
767 button = rb->button_get_w_tmo(HZ/25);
770 switch (button)
772 case CUBE_INC:
773 case CUBE_INC|BUTTON_REPEAT:
774 if (!paused)
776 if (axes[curr].speed < 10)
777 axes[curr].speed++;
779 else
781 if (++axes[curr].angle > 359)
782 axes[curr].angle -= 360;
784 t_disp = DISP_TIME;
785 redraw = true;
786 break;
788 case CUBE_DEC:
789 case CUBE_DEC|BUTTON_REPEAT:
790 if (!paused)
792 if (axes[curr].speed > -10)
793 axes[curr].speed--;
795 else
797 if (--axes[curr].angle < 0)
798 axes[curr].angle += 360;
800 t_disp = DISP_TIME;
801 redraw = true;
802 break;
804 case CUBE_NEXT:
805 if (++curr > 2)
806 curr = 0;
807 t_disp = DISP_TIME;
808 break;
810 case CUBE_PREV:
811 if (--curr < 0)
812 curr = 2;
813 t_disp = DISP_TIME;
814 break;
816 case CUBE_MODE:
817 #ifdef CUBE_MODE_PRE
818 if (lastbutton != CUBE_MODE_PRE)
819 break;
820 #endif
821 if (++mode >= NUM_MODES)
822 mode = 0;
823 #ifdef USEGSLIB
824 mylcd = (mode == SOLID) ? &greyfuncs : &lcdfuncs;
825 mode_switch = true;
826 #endif
827 redraw = true;
828 break;
830 case CUBE_PAUSE:
831 #ifdef CUBE_PAUSE_PRE
832 if (lastbutton != CUBE_PAUSE_PRE)
833 break;
834 #endif
835 paused = !paused;
836 break;
838 case CUBE_HIGHSPEED:
839 #ifdef CUBE_HIGHSPEED_PRE
840 if (lastbutton != CUBE_HIGHSPEED_PRE)
841 break;
842 #endif
843 highspeed = !highspeed;
844 t_disp = DISP_TIME;
845 break;
847 #ifdef CUBE_RC_QUIT
848 case CUBE_RC_QUIT:
849 #endif
850 case CUBE_QUIT:
851 exit(EXIT_SUCCESS);
852 break;
854 default:
855 exit_on_usb(button);
856 break;
858 if (button != BUTTON_NONE)
859 lastbutton = button;
862 return PLUGIN_OK;