Fix yellow
[Rockbox.git] / apps / plugins / cube.c
blobbc5564b47326aae4928f9b0871ec0c7147f97c93
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 "grey.h"
23 #include "playergfx.h"
24 #include "xlcd.h"
25 #include "fixedpoint.h"
27 PLUGIN_HEADER
29 /* Loops that the values are displayed */
30 #define DISP_TIME 30
32 /* variable button definitions */
33 #if CONFIG_KEYPAD == RECORDER_PAD
34 #define CUBE_QUIT BUTTON_OFF
35 #define CUBE_X_INC BUTTON_RIGHT
36 #define CUBE_X_DEC BUTTON_LEFT
37 #define CUBE_Y_INC BUTTON_UP
38 #define CUBE_Y_DEC BUTTON_DOWN
39 #define CUBE_Z_INC BUTTON_F2
40 #define CUBE_Z_DEC BUTTON_F1
41 #define CUBE_MODE BUTTON_F3
42 #define CUBE_PAUSE BUTTON_PLAY
43 #define CUBE_HIGHSPEED BUTTON_ON
45 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
46 #define CUBE_QUIT BUTTON_OFF
47 #define CUBE_X_INC BUTTON_RIGHT
48 #define CUBE_X_DEC BUTTON_LEFT
49 #define CUBE_Y_INC BUTTON_UP
50 #define CUBE_Y_DEC BUTTON_DOWN
51 #define CUBE_Z_INC BUTTON_F2
52 #define CUBE_Z_DEC BUTTON_F1
53 #define CUBE_MODE BUTTON_F3
54 #define CUBE_PAUSE BUTTON_SELECT
55 #define CUBE_HIGHSPEED BUTTON_ON
57 #elif CONFIG_KEYPAD == PLAYER_PAD
58 #define CUBE_QUIT BUTTON_STOP
59 #define CUBE_X_INC BUTTON_RIGHT
60 #define CUBE_X_DEC BUTTON_LEFT
61 #define CUBE_Y_INC (BUTTON_ON | BUTTON_RIGHT)
62 #define CUBE_Y_DEC (BUTTON_ON | BUTTON_LEFT)
63 #define CUBE_Z_INC (BUTTON_MENU | BUTTON_RIGHT)
64 #define CUBE_Z_DEC (BUTTON_MENU | BUTTON_LEFT)
65 #define CUBE_MODE_PRE BUTTON_MENU
66 #define CUBE_MODE (BUTTON_MENU | BUTTON_REL)
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_X_INC BUTTON_RIGHT
74 #define CUBE_X_DEC BUTTON_LEFT
75 #define CUBE_Y_INC BUTTON_UP
76 #define CUBE_Y_DEC BUTTON_DOWN
77 #define CUBE_Z_INC (BUTTON_MENU | BUTTON_UP)
78 #define CUBE_Z_DEC (BUTTON_MENU | BUTTON_DOWN)
79 #define CUBE_MODE_PRE BUTTON_MENU
80 #define CUBE_MODE (BUTTON_MENU | BUTTON_REL)
81 #define CUBE_PAUSE (BUTTON_MENU | BUTTON_LEFT)
82 #define CUBE_HIGHSPEED (BUTTON_MENU | BUTTON_RIGHT)
84 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
85 (CONFIG_KEYPAD == IRIVER_H300_PAD)
86 #define CUBE_QUIT BUTTON_OFF
87 #define CUBE_X_INC BUTTON_RIGHT
88 #define CUBE_X_DEC BUTTON_LEFT
89 #define CUBE_Y_INC BUTTON_UP
90 #define CUBE_Y_DEC BUTTON_DOWN
91 #define CUBE_Z_INC (BUTTON_ON | BUTTON_UP)
92 #define CUBE_Z_DEC (BUTTON_ON | BUTTON_DOWN)
93 #define CUBE_MODE BUTTON_MODE
94 #define CUBE_PAUSE_PRE BUTTON_ON
95 #define CUBE_PAUSE (BUTTON_ON | BUTTON_REL)
96 #define CUBE_HIGHSPEED BUTTON_SELECT
98 #define CUBE_RC_QUIT BUTTON_RC_STOP
100 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
101 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
102 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
103 #define CUBE_QUIT BUTTON_MENU
104 #define CUBE_X_INC BUTTON_RIGHT
105 #define CUBE_X_DEC BUTTON_LEFT
106 #define CUBE_Y_INC BUTTON_SCROLL_FWD
107 #define CUBE_Y_DEC BUTTON_SCROLL_BACK
108 #define CUBE_Z_INC (BUTTON_SELECT | BUTTON_RIGHT)
109 #define CUBE_Z_DEC (BUTTON_SELECT | BUTTON_LEFT)
110 #define CUBE_MODE (BUTTON_SELECT | BUTTON_MENU)
111 #define CUBE_PAUSE_PRE BUTTON_PLAY
112 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
113 #define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_PLAY)
115 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
116 #define CUBE_QUIT BUTTON_PLAY
117 #define CUBE_X_INC BUTTON_RIGHT
118 #define CUBE_X_DEC BUTTON_LEFT
119 #define CUBE_Y_INC BUTTON_UP
120 #define CUBE_Y_DEC BUTTON_DOWN
121 #define CUBE_Z_INC BUTTON_MODE
122 #define CUBE_Z_DEC BUTTON_EQ
123 #define CUBE_MODE (BUTTON_SELECT | BUTTON_REPEAT)
124 #define CUBE_PAUSE (BUTTON_SELECT | BUTTON_REL)
125 #define CUBE_HIGHSPEED (BUTTON_MODE | BUTTON_EQ) /* TODO: this is impossible */
127 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
128 #define CUBE_QUIT BUTTON_POWER
129 #define CUBE_X_INC BUTTON_LEFT
130 #define CUBE_X_DEC BUTTON_RIGHT
131 #define CUBE_Y_INC BUTTON_UP
132 #define CUBE_Y_DEC BUTTON_DOWN
133 #define CUBE_Z_INC (BUTTON_PLAY | BUTTON_UP)
134 #define CUBE_Z_DEC (BUTTON_PLAY | BUTTON_DOWN)
135 #define CUBE_MODE BUTTON_SELECT
136 #define CUBE_PAUSE_PRE BUTTON_PLAY
137 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
138 #define CUBE_HIGHSPEED (BUTTON_REC | BUTTON_REL)
140 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
141 #define CUBE_QUIT BUTTON_POWER
142 #define CUBE_X_INC BUTTON_LEFT
143 #define CUBE_X_DEC BUTTON_RIGHT
144 #define CUBE_Y_INC BUTTON_UP
145 #define CUBE_Y_DEC BUTTON_DOWN
146 #define CUBE_Z_INC BUTTON_VOL_UP
147 #define CUBE_Z_DEC BUTTON_VOL_DOWN
148 #define CUBE_MODE BUTTON_MENU
149 #define CUBE_PAUSE BUTTON_SELECT
150 #define CUBE_HIGHSPEED BUTTON_A
152 #elif (CONFIG_KEYPAD == SANSA_E200_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_FWD
157 #define CUBE_Y_DEC BUTTON_SCROLL_BACK
158 #define CUBE_Z_INC BUTTON_UP
159 #define CUBE_Z_DEC BUTTON_DOWN
160 #define CUBE_MODE_PRE BUTTON_SELECT
161 #define CUBE_MODE (BUTTON_SELECT|BUTTON_REPEAT)
162 #define CUBE_PAUSE_PRE BUTTON_SELECT
163 #define CUBE_PAUSE (BUTTON_SELECT|BUTTON_REL)
164 #define CUBE_HIGHSPEED BUTTON_REC
166 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
167 #define CUBE_QUIT BUTTON_POWER
168 #define CUBE_X_INC BUTTON_LEFT
169 #define CUBE_X_DEC BUTTON_RIGHT
170 #define CUBE_Y_INC BUTTON_VOL_UP
171 #define CUBE_Y_DEC BUTTON_VOL_DOWN
172 #define CUBE_Z_INC BUTTON_UP
173 #define CUBE_Z_DEC BUTTON_DOWN
174 #define CUBE_MODE_PRE BUTTON_SELECT
175 #define CUBE_MODE (BUTTON_SELECT|BUTTON_REPEAT)
176 #define CUBE_PAUSE_PRE BUTTON_SELECT
177 #define CUBE_PAUSE (BUTTON_SELECT|BUTTON_REL)
178 #define CUBE_HIGHSPEED BUTTON_REC
181 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
182 #define CUBE_QUIT BUTTON_POWER
183 #define CUBE_X_INC BUTTON_LEFT
184 #define CUBE_X_DEC BUTTON_RIGHT
185 #define CUBE_Y_INC BUTTON_SCROLL_UP
186 #define CUBE_Y_DEC BUTTON_SCROLL_DOWN
187 #define CUBE_Z_INC (BUTTON_PLAY | BUTTON_SCROLL_UP)
188 #define CUBE_Z_DEC (BUTTON_PLAY | BUTTON_SCROLL_DOWN)
189 #define CUBE_MODE BUTTON_REW
190 #define CUBE_PAUSE_PRE BUTTON_PLAY
191 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
192 #define CUBE_HIGHSPEED (BUTTON_FF | BUTTON_REL)
194 #elif CONFIG_KEYPAD == MROBE500_PAD
195 #define CUBE_QUIT BUTTON_POWER
196 #define CUBE_X_INC BUTTON_LEFT
197 #define CUBE_X_DEC BUTTON_RIGHT
198 #define CUBE_Y_INC BUTTON_RC_PLAY
199 #define CUBE_Y_DEC BUTTON_RC_DOWN
200 #define CUBE_Z_INC BUTTON_RC_VOL_UP
201 #define CUBE_Z_DEC BUTTON_RC_VOL_DOWN
202 #define CUBE_MODE BUTTON_RC_MODE
203 #define CUBE_PAUSE_PRE BUTTON_RC_HEART
204 #define CUBE_PAUSE (BUTTON_RC_HEART | BUTTON_REL)
205 #define CUBE_HIGHSPEED BUTTON_RC_HEART
207 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
208 #define CUBE_QUIT BUTTON_BACK
209 #define CUBE_X_INC BUTTON_LEFT
210 #define CUBE_X_DEC BUTTON_RIGHT
211 #define CUBE_Y_INC BUTTON_UP
212 #define CUBE_Y_DEC BUTTON_DOWN
213 #define CUBE_Z_INC BUTTON_VOL_UP
214 #define CUBE_Z_DEC BUTTON_VOL_DOWN
215 #define CUBE_MODE BUTTON_PREV
216 #define CUBE_PAUSE_PRE BUTTON_PLAY
217 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
218 #define CUBE_HIGHSPEED (BUTTON_NEXT | BUTTON_REL)
220 #elif (CONFIG_KEYPAD == MROBE100_PAD)
221 #define CUBE_QUIT BUTTON_POWER
222 #define CUBE_X_INC BUTTON_LEFT
223 #define CUBE_X_DEC BUTTON_RIGHT
224 #define CUBE_Y_INC BUTTON_UP
225 #define CUBE_Y_DEC BUTTON_DOWN
226 #define CUBE_Z_INC (BUTTON_DISPLAY | BUTTON_UP)
227 #define CUBE_Z_DEC (BUTTON_DISPLAY | BUTTON_DOWN)
228 #define CUBE_MODE BUTTON_MENU
229 #define CUBE_PAUSE BUTTON_PLAY
230 #define CUBE_HIGHSPEED BUTTON_SELECT
232 #elif (CONFIG_KEYPAD == IAUDIO_M3_PAD)
233 #define CUBE_QUIT BUTTON_RC_REC
234 #define CUBE_X_INC BUTTON_RC_FF
235 #define CUBE_X_DEC BUTTON_RC_REW
236 #define CUBE_Y_INC BUTTON_RC_VOL_UP
237 #define CUBE_Y_DEC BUTTON_RC_VOL_DOWN
238 #define CUBE_Z_INC BUTTON_VOL_UP /* FIXME: quick hack */
239 #define CUBE_Z_DEC BUTTON_VOL_DOWN
240 #define CUBE_MODE BUTTON_RC_MODE
241 #define CUBE_PAUSE BUTTON_RC_PLAY
242 #define CUBE_HIGHSPEED BUTTON_RC_MENU
244 #elif CONFIG_KEYPAD == COWOND2_PAD
245 #define CUBE_QUIT BUTTON_POWER
247 #else
248 #error No keymap defined!
249 #endif
251 #ifdef HAVE_TOUCHPAD
252 // not enough touchfields, so CUBE_QUIT have to be
253 // mapped to a real button
254 //ifndef CUBE_QUIT
255 //#define CUBE_QUIT BUTTON_TOPLEFT
256 //#endif
257 #ifndef CUBE_X_INC
258 #define CUBE_X_INC BUTTON_MIDRIGHT
259 #endif
260 #ifndef CUBE_X_DEC
261 #define CUBE_X_DEC BUTTON_MIDLEFT
262 #endif
263 #ifndef CUBE_Y_INC
264 #define CUBE_Y_INC BUTTON_TOPMIDDLE
265 #endif
266 #ifndef CUBE_Y_DEC
267 #define CUBE_Y_DEC BUTTON_BOTTOMMIDDLE
268 #endif
269 #ifndef CUBE_Z_INC
270 #define CUBE_Z_INC BUTTON_BOTTOMRIGHT
271 #endif
272 #ifndef CUBE_Z_DEC
273 #define CUBE_Z_DEC BUTTON_BOTTOMLEFT
274 #endif
275 #ifndef CUBE_MODE
276 #define CUBE_MODE BUTTON_TOPRIGHT
277 #endif
278 #ifndef CUBE_PAUSE
279 #define CUBE_PAUSE (BUTTON_CENTER | BUTTON_REL)
280 #endif
281 #ifndef CUBE_HIGHSPEED
282 #define CUBE_HIGHSPEED BUTTON_TOPLEFT
283 #endif
284 #endif
287 #ifdef HAVE_LCD_BITMAP
289 #define DIST (10 * MIN(LCD_HEIGHT, LCD_WIDTH) / 16)
290 static int x_off = LCD_WIDTH/2;
291 static int y_off = LCD_HEIGHT/2;
293 #if LCD_DEPTH == 1
294 #define USE_GSLIB
295 GREY_INFO_STRUCT
296 struct my_lcd {
297 void (*update)(void);
298 void (*clear_display)(void);
299 void (*drawline)(int x1, int y1, int x2, int y2);
300 void (*putsxy)(int x, int y, const unsigned char *string);
303 static struct my_lcd greyfuncs = {
304 grey_update, grey_clear_display, grey_drawline, grey_putsxy
306 static struct my_lcd lcdfuncs; /* initialised at runtime */
307 static struct my_lcd *mylcd = &greyfuncs;
309 #define MYLCD(fn) mylcd->fn
310 #define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) grey_filltriangle(x1, y1, x2, y2, x3, y3)
311 #define MY_SET_FOREGROUND(fg) grey_set_foreground(fg)
312 #define MY_GET_FOREGROUND() grey_get_foreground()
314 #else
315 #define MYLCD(fn) rb->lcd_ ## fn
316 #define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) xlcd_filltriangle(x1, y1, x2, y2, x3, y3)
317 #define MY_SET_FOREGROUND(fg) rb->lcd_set_foreground(fg)
318 #define MY_GET_FOREGROUND() rb->lcd_get_foreground()
319 #endif
321 #if CONFIG_LCD == LCD_SSD1815
322 #define ASPECT 320 /* = 1.25 (fixed point 24.8) */
323 #else
324 #define ASPECT 256 /* = 1.00 */
325 #endif
327 #else /* !LCD_BITMAP */
329 #define MYLCD(fn) pgfx_ ## fn
330 #define DIST 9
331 static int x_off = 10;
332 static int y_off = 7;
333 #define ASPECT 300 /* = 1.175 */
335 #endif /* !LCD_BITMAP */
337 struct point_3D {
338 long x, y, z;
341 struct point_2D {
342 long x, y;
345 struct line {
346 int start, end;
349 struct face {
350 int corner[4];
351 int line[4];
354 /* initial, unrotated cube corners */
355 static const struct point_3D sommet[8] =
357 {-DIST, -DIST, -DIST},
358 { DIST, -DIST, -DIST},
359 { DIST, DIST, -DIST},
360 {-DIST, DIST, -DIST},
361 {-DIST, -DIST, DIST},
362 { DIST, -DIST, DIST},
363 { DIST, DIST, DIST},
364 {-DIST, DIST, DIST}
367 /* The 12 lines forming the edges */
368 static const struct line lines[12] =
370 {0, 1}, {1, 2}, {2, 3}, {3, 0},
371 {4, 7}, {7, 6}, {6, 5}, {5, 4},
372 {0, 4}, {1, 5}, {2, 6}, {3, 7}
375 static bool lines_drawn[12];
377 /* The 6 faces of the cube; points are in clockwise order when viewed
378 from the outside */
379 static const struct face faces[6] =
381 {{0, 1, 2, 3}, {0, 1, 2, 3}},
382 {{4, 7, 6, 5}, {4, 5, 6, 7}},
383 {{0, 4, 5, 1}, {8, 7, 9, 0}},
384 {{2, 6, 7, 3}, {10, 5, 11, 2}},
385 {{0, 3, 7, 4}, {3, 11, 4, 8}},
386 {{1, 5, 6, 2}, {9, 6, 10, 1}}
389 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
390 static const unsigned face_colors[6] =
392 #ifdef HAVE_LCD_COLOR
393 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0),
394 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255)
395 #elif defined(USE_GSLIB)
396 #ifdef MROBE_100
397 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
398 GREY_DARKGRAY, GREY_WHITE, GREY_WHITE
399 #else
400 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
401 GREY_DARKGRAY, GREY_BLACK, GREY_BLACK
402 #endif
403 #else
404 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY,
405 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK
406 #endif
408 #endif
410 enum {
411 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
412 SOLID,
413 #endif
414 HIDDEN_LINES,
415 WIREFRAME,
416 NUM_MODES
419 static int mode = 0;
421 static struct point_3D point3D[8];
422 static struct point_2D point2D[8];
423 static long matrice[3][3];
425 static const int nb_points = 8;
426 static long z_off = 600;
428 static const struct plugin_api* rb;
430 static void cube_rotate(int xa, int ya, int za)
432 int i;
433 /* Just to prevent unnecessary lookups */
434 long sxa, cxa, sya, cya, sza, cza;
436 sxa = sin_int(xa);
437 cxa = cos_int(xa);
438 sya = sin_int(ya);
439 cya = cos_int(ya);
440 sza = sin_int(za);
441 cza = cos_int(za);
443 /* calculate overall translation matrix */
444 matrice[0][0] = (cza * cya) >> 14;
445 matrice[1][0] = (sza * cya) >> 14;
446 matrice[2][0] = -sya;
448 matrice[0][1] = (((cza * sya) >> 14) * sxa - sza * cxa) >> 14;
449 matrice[1][1] = (((sza * sya) >> 14) * sxa + cxa * cza) >> 14;
450 matrice[2][1] = (sxa * cya) >> 14;
452 matrice[0][2] = (((cza * sya) >> 14) * cxa + sza * sxa) >> 14;
453 matrice[1][2] = (((sza * sya) >> 14) * cxa - cza * sxa) >> 14;
454 matrice[2][2] = (cxa * cya) >> 14;
456 /* apply translation matrix to all points */
457 for (i = 0; i < nb_points; i++)
459 point3D[i].x = matrice[0][0] * sommet[i].x + matrice[1][0] * sommet[i].y
460 + matrice[2][0] * sommet[i].z;
462 point3D[i].y = matrice[0][1] * sommet[i].x + matrice[1][1] * sommet[i].y
463 + matrice[2][1] * sommet[i].z;
465 point3D[i].z = matrice[0][2] * sommet[i].x + matrice[1][2] * sommet[i].y
466 + matrice[2][2] * sommet[i].z;
470 static void cube_viewport(void)
472 int i;
474 /* Do viewport transformation for all points */
475 for (i = 0; i < nb_points; i++)
477 #if ASPECT != 256
478 point2D[i].x = (point3D[i].x * ASPECT) / (point3D[i].z + (z_off << 14))
479 + x_off;
480 #else
481 point2D[i].x = (point3D[i].x << 8) / (point3D[i].z + (z_off << 14))
482 + x_off;
483 #endif
484 point2D[i].y = (point3D[i].y << 8) / (point3D[i].z + (z_off << 14))
485 + y_off;
489 static void cube_draw(void)
491 int i, j, line;
492 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
493 unsigned old_foreground;
494 #endif
496 switch (mode)
498 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
499 case SOLID:
501 old_foreground = MY_GET_FOREGROUND();
502 for (i = 0; i < 6; i++)
504 /* backface culling; if the shape winds counter-clockwise, we are
505 * looking at the backface, and the (simplified) cross product
506 * is < 0. Do not draw it. */
507 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
508 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
509 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
510 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
511 continue;
513 MY_SET_FOREGROUND(face_colors[i]);
514 MY_FILLTRIANGLE(point2D[faces[i].corner[0]].x,
515 point2D[faces[i].corner[0]].y,
516 point2D[faces[i].corner[1]].x,
517 point2D[faces[i].corner[1]].y,
518 point2D[faces[i].corner[2]].x,
519 point2D[faces[i].corner[2]].y);
520 MY_FILLTRIANGLE(point2D[faces[i].corner[0]].x,
521 point2D[faces[i].corner[0]].y,
522 point2D[faces[i].corner[2]].x,
523 point2D[faces[i].corner[2]].y,
524 point2D[faces[i].corner[3]].x,
525 point2D[faces[i].corner[3]].y);
528 MY_SET_FOREGROUND(old_foreground);
529 break;
530 #endif /* (LCD_DEPTH > 1) || GSLIB */
532 case HIDDEN_LINES:
534 rb->memset(lines_drawn, 0, sizeof(lines_drawn));
535 for (i = 0; i < 6; i++)
537 /* backface culling; if the shape winds counter-clockwise, we are
538 * looking at the backface, and the (simplified) cross product
539 * is < 0. Do not draw it. */
540 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
541 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
542 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
543 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
544 continue;
546 for (j = 0; j < 4; j++)
548 line = faces[i].line[j];
549 if (!lines_drawn[line])
551 lines_drawn[line] = true;
552 MYLCD(drawline)(point2D[lines[line].start].x,
553 point2D[lines[line].start].y,
554 point2D[lines[line].end].x,
555 point2D[lines[line].end].y);
559 break;
561 case WIREFRAME:
563 for (i = 0; i < 12; i++)
564 MYLCD(drawline)(point2D[lines[i].start].x,
565 point2D[lines[i].start].y,
566 point2D[lines[i].end].x,
567 point2D[lines[i].end].y);
568 break;
572 void cleanup(void *parameter)
574 (void)parameter;
576 #ifdef USE_GSLIB
577 grey_release();
578 #elif defined HAVE_LCD_CHARCELLS
579 pgfx_release();
580 #endif
583 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
585 char buffer[30];
586 int t_disp = 0;
587 #ifdef USE_GSLIB
588 unsigned char *gbuf;
589 size_t gbuf_size = 0;
590 bool mode_switch = true;
591 #endif
593 int button;
594 int lastbutton = BUTTON_NONE;
595 int xa = 0;
596 int ya = 0;
597 int za = 0;
598 int xs = 1;
599 int ys = 3;
600 int zs = 1;
601 bool highspeed = false;
602 bool paused = false;
603 bool redraw = true;
604 bool exit = false;
606 (void)(parameter);
607 rb = api;
609 #ifdef HAVE_LCD_BITMAP
610 #if LCD_DEPTH > 1
611 xlcd_init(rb);
612 #elif defined(USE_GSLIB)
613 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size);
614 if (!grey_init(rb, gbuf, gbuf_size, GREY_BUFFERED,
615 LCD_WIDTH, LCD_HEIGHT, NULL))
617 rb->splash(HZ, "Couldn't init greyscale display");
618 return PLUGIN_ERROR;
620 /* init lcd_ function pointers */
621 lcdfuncs.update = rb->lcd_update;
622 lcdfuncs.clear_display = rb->lcd_clear_display;
623 lcdfuncs.drawline = rb->lcd_drawline;
624 lcdfuncs.putsxy = rb->lcd_putsxy;
626 #ifdef MROBE_100
627 grey_set_background(GREY_BLACK);
628 #endif
630 grey_setfont(FONT_SYSFIXED);
631 #endif
632 rb->lcd_setfont(FONT_SYSFIXED);
633 #else /* LCD_CHARCELLS */
634 if (!pgfx_init(rb, 4, 2))
636 rb->splash(HZ*2, "Old LCD :(");
637 return PLUGIN_OK;
639 pgfx_display(3, 0);
640 #endif
642 while(!exit)
644 if (highspeed)
645 rb->yield();
646 else
647 rb->sleep(4);
649 if (redraw)
651 MYLCD(clear_display)();
652 cube_rotate(xa, ya, za);
653 cube_viewport();
654 cube_draw();
655 redraw = false;
658 #ifdef HAVE_LCD_BITMAP
659 if (t_disp > 0)
661 t_disp--;
662 rb->snprintf(buffer, sizeof(buffer), "x:%d y:%d z:%d h:%d",
663 xs, ys, zs, highspeed);
664 MYLCD(putsxy)(0, LCD_HEIGHT-8, buffer);
665 if (t_disp == 0)
666 redraw = true;
668 #else
669 if (t_disp > 0)
671 if (t_disp == DISP_TIME)
673 rb->snprintf(buffer, sizeof(buffer), "x%d", xs);
674 rb->lcd_puts(0, 0, buffer);
675 rb->snprintf(buffer, sizeof(buffer), "y%d", ys);
676 rb->lcd_puts(0, 1, buffer);
677 pgfx_display(3, 0);
678 rb->snprintf(buffer, sizeof(buffer), "z%d", zs);
679 rb->lcd_puts(8, 0, buffer);
680 rb->snprintf(buffer, sizeof(buffer), "h%d", highspeed);
681 rb->lcd_puts(8, 1, buffer);
683 t_disp--;
684 if (t_disp == 0)
686 rb->lcd_clear_display();
687 pgfx_display(3, 0);
690 #endif
691 #ifdef USE_GSLIB
692 if (mode_switch)
694 grey_show(mode == SOLID);
695 mode_switch = false;
697 #endif
698 MYLCD(update)();
700 if (!paused)
702 xa += xs;
703 if (xa > 359)
704 xa -= 360;
705 else if (xa < 0)
706 xa += 360;
708 ya += ys;
709 if (ya > 359)
710 ya -= 360;
711 else if (ya < 0)
712 ya += 360;
714 za += zs;
715 if (za > 359)
716 za -= 360;
717 else if (za < 0)
718 za += 360;
719 redraw = true;
722 button = rb->button_get(false);
723 switch (button)
725 case CUBE_X_INC:
726 case (CUBE_X_INC|BUTTON_REPEAT):
727 if( !paused )
729 if( xs < 10)
730 xs++;
732 else
734 xa++;
735 if( xa > 359 )
736 xa -= 360;
738 t_disp = DISP_TIME;
739 redraw = true;
740 break;
742 case CUBE_X_DEC:
743 case (CUBE_X_DEC|BUTTON_REPEAT):
744 if( !paused )
746 if (xs > -10)
747 xs--;
749 else
751 xa--;
752 if( xa < 0 )
753 xa += 360;
755 t_disp = DISP_TIME;
756 redraw = true;
757 break;
759 case CUBE_Y_INC:
760 case (CUBE_Y_INC|BUTTON_REPEAT):
761 if( !paused )
763 if (ys < 10)
764 ys++;
766 else
768 ya++;
769 if( ya > 359 )
770 ya -= 360;
772 t_disp = DISP_TIME;
773 redraw = true;
774 break;
776 case CUBE_Y_DEC:
777 case (CUBE_Y_DEC|BUTTON_REPEAT):
778 if( !paused )
780 if (ys > -10)
781 ys--;
783 else
785 ya--;
786 if( ya < 0 )
787 ya += 360;
789 t_disp = DISP_TIME;
790 redraw = true;
791 break;
793 case CUBE_Z_INC:
794 case (CUBE_Z_INC|BUTTON_REPEAT):
795 if( !paused )
797 if (zs < 10)
798 zs++;
800 else
802 za++;
803 if( za > 359 )
804 za -= 360;
806 t_disp = DISP_TIME;
807 redraw = true;
808 break;
810 case CUBE_Z_DEC:
811 case (CUBE_Z_DEC|BUTTON_REPEAT):
812 if( !paused )
814 if (zs > -10)
815 zs--;
817 else
819 za--;
820 if( za < 0 )
821 za += 360;
823 t_disp = DISP_TIME;
824 redraw = true;
825 break;
827 case CUBE_MODE:
828 #ifdef CUBE_MODE_PRE
829 if (lastbutton != CUBE_MODE_PRE)
830 break;
831 #endif
832 if (++mode >= NUM_MODES)
833 mode = 0;
834 #ifdef USE_GSLIB
835 mylcd = (mode == SOLID) ? &greyfuncs : &lcdfuncs;
836 mode_switch = true;
837 #endif
838 redraw = true;
839 break;
841 case CUBE_PAUSE:
842 #ifdef CUBE_PAUSE_PRE
843 if (lastbutton != CUBE_PAUSE_PRE)
844 break;
845 #endif
846 paused = !paused;
847 break;
849 case CUBE_HIGHSPEED:
850 #ifdef CUBE_HIGHSPEED_PRE
851 if (lastbutton != CUBE_HIGHSPEED_PRE)
852 break;
853 #endif
854 highspeed = !highspeed;
855 t_disp = DISP_TIME;
856 break;
858 #ifdef CUBE_RC_QUIT
859 case CUBE_RC_QUIT:
860 #endif
861 case CUBE_QUIT:
862 exit = true;
863 break;
865 default:
866 if (rb->default_event_handler_ex(button, cleanup, NULL)
867 == SYS_USB_CONNECTED)
868 return PLUGIN_USB_CONNECTED;
869 break;
871 if (button != BUTTON_NONE)
872 lastbutton = button;
875 #ifdef USE_GSLIB
876 grey_release();
877 #elif defined(HAVE_LCD_CHARCELLS)
878 pgfx_release();
879 #endif
880 return PLUGIN_OK;