summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/puzzles/puzzles.make4
-rw-r--r--apps/plugins/puzzles/rockbox.c405
-rw-r--r--apps/plugins/puzzles/untangle.c15
3 files changed, 327 insertions, 97 deletions
diff --git a/apps/plugins/puzzles/puzzles.make b/apps/plugins/puzzles/puzzles.make
index 4052423fb9..f49b663197 100644
--- a/apps/plugins/puzzles/puzzles.make
+++ b/apps/plugins/puzzles/puzzles.make
@@ -43,8 +43,8 @@ ROCKS += $(PUZZLES_ROCKS)
43endif 43endif
44 44
45# Hack to suppress all warnings: 45# Hack to suppress all warnings:
46PUZZLESFLAGS = $(filter-out -O%,$(PLUGINFLAGS)) -Os \ 46PUZZLESFLAGS = $(filter-out -O%,$(PLUGINFLAGS)) -O3 \
47 -Wno-unused-parameter -Wno-sign-compare -Wno-strict-aliasing -w \ 47 -Wno-unused-parameter -Wno-sign-compare -Wno-strict-aliasing -w \
48 -DFOR_REAL -I$(PUZZLES_SRCDIR) 48 -DFOR_REAL -I$(PUZZLES_SRCDIR)
49ifdef PUZZLES_COMBINED 49ifdef PUZZLES_COMBINED
50PUZZLESFLAGS += -DCOMBINED 50PUZZLESFLAGS += -DCOMBINED
diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c
index 3e3bd15f33..dc8d4c9645 100644
--- a/apps/plugins/puzzles/rockbox.c
+++ b/apps/plugins/puzzles/rockbox.c
@@ -30,6 +30,7 @@
30#include "lib/playback_control.h" 30#include "lib/playback_control.h"
31#endif 31#endif
32#include "lib/xlcd.h" 32#include "lib/xlcd.h"
33#include "fixedpoint.h"
33 34
34/* how many ticks between timer callbacks */ 35/* how many ticks between timer callbacks */
35#define TIMER_INTERVAL (HZ / 50) 36#define TIMER_INTERVAL (HZ / 50)
@@ -75,7 +76,7 @@ extern bool audiobuf_available;
75 76
76static struct settings_t { 77static struct settings_t {
77 int slowmo_factor; 78 int slowmo_factor;
78 bool bulk, timerflash, clipoff; 79 bool bulk, timerflash, clipoff, shortcuts, no_aa;
79} settings; 80} settings;
80 81
81/* clipping is implemented through viewports and offsetting 82/* clipping is implemented through viewports and offsetting
@@ -179,14 +180,139 @@ static void rb_draw_rect(void *handle, int x, int y, int w, int h, int color)
179 rb->lcd_fillrect(x, y, w, h); 180 rb->lcd_fillrect(x, y, w, h);
180} 181}
181 182
183#define SWAP(a, b, t) do { t = a; a = b; b = t; } while(0);
184
185#define fp_fpart(f, bits) ((f) & ((1 << (bits)) - 1))
186#define fp_rfpart(f, bits) ((1 << (bits)) - fp_fpart(f, bits))
187
188#define FRACBITS 16
189
190/* most of our time drawing lines is spent in this function! */
191static inline void plot(unsigned x, unsigned y, unsigned long a,
192 unsigned long r1, unsigned long g1, unsigned long b1,
193 unsigned cl, unsigned cr, unsigned cu, unsigned cd)
194{
195 /* This is really quite possibly the least efficient way of doing
196 this. A better way would be in draw_antialiased_line(), but the
197 problem with that is that the algorithms I investigated at
198 least were incorrect at least part of the time and didn't make
199 drawing much faster overall. */
200 if(!(cl <= x && x < cr && cu <= y && y < cd))
201 return;
202
203 fb_data *ptr = rb->lcd_framebuffer + y * LCD_WIDTH + x;
204 fb_data orig = *ptr;
205 unsigned long r2, g2, b2;
206#if LCD_DEPTH != 24
207 r2 = RGB_UNPACK_RED(orig);
208 g2 = RGB_UNPACK_GREEN(orig);
209 b2 = RGB_UNPACK_BLUE(orig);
210#lse
211 r2 = orig.r;
212 g2 = orig.g;
213 b2 = orig.b;
214#endif
215
216 unsigned long r, g, b;
217 r = ((r1 * a) + (r2 * (256 - a))) >> 8;
218 g = ((g1 * a) + (g2 * (256 - a))) >> 8;
219 b = ((b1 * a) + (b2 * (256 - a))) >> 8;
220
221#if LCD_DEPTH != 24
222 *ptr = LCD_RGBPACK(r, g, b);
223#else
224 *ptr = (fb_data) {b, g, r};
225#endif
226}
227
228#undef ABS
229#define ABS(a) ((a)<0?-(a):(a))
230
231/* speed benchmark: 34392 lines/sec vs 112687 non-antialiased
232 * lines/sec at full optimization on ipod6g */
233
234/* expects UN-OFFSET coordinates, directly access framebuffer */
235static void draw_antialiased_line(int x0, int y0, int x1, int y1)
236{
237 /* fixed-point Wu's algorithm, modified for integer-only endpoints */
238
239 /* passed to plot() to avoid re-calculation */
240 unsigned short l = 0, r = LCD_WIDTH, u = 0, d = LCD_HEIGHT;
241 if(clipped)
242 {
243 l = clip_rect.x;
244 r = clip_rect.x + clip_rect.width;
245 u = clip_rect.y;
246 d = clip_rect.y + clip_rect.height;
247 }
248
249 bool steep = ABS(y1 - y0) > ABS(x1 - x0);
250 int tmp;
251 if(steep)
252 {
253 SWAP(x0, y0, tmp);
254 SWAP(x1, y1, tmp);
255 }
256 if(x0 > x1)
257 {
258 SWAP(x0, x1, tmp);
259 SWAP(y0, y1, tmp);
260 }
261
262 int dx, dy;
263 dx = x1 - x0;
264 dy = y1 - y0;
265
266 if(!(dx << FRACBITS))
267 return; /* bail out */
268
269 long gradient = fp_div(dy << FRACBITS, dx << FRACBITS, FRACBITS);
270 long intery = (y0 << FRACBITS);
271
272 unsigned color = rb->lcd_get_foreground();
273 unsigned long r1, g1, b1;
274 r1 = RGB_UNPACK_RED(color);
275 g1 = RGB_UNPACK_GREEN(color);
276 b1 = RGB_UNPACK_BLUE(color);
277
278 /* main loop */
279 if(steep)
280 {
281 for(int x = x0; x <= x1; ++x, intery += gradient)
282 {
283 unsigned y = intery >> FRACBITS;
284 unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8);
285
286 plot(y, x, (1 << 8) - alpha, r1, g1, b1, l, r, u, d);
287 plot(y + 1, x, alpha, r1, g1, b1, l, r, u, d);
288 }
289 }
290 else
291 {
292 for(int x = x0; x <= x1; ++x, intery += gradient)
293 {
294 unsigned y = intery >> FRACBITS;
295 unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8);
296
297 plot(x, y, (1 << 8) - alpha, r1, g1, b1, l, r, u, d);
298 plot(x, y + 1, alpha, r1, g1, b1, l, r, u, d);
299 }
300 }
301}
302
182static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2, 303static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2,
183 int color) 304 int color)
184{ 305{
185 LOGF("rb_draw_line(%d, %d, %d, %d, %d)", x1, y1, x2, y2, color); 306 LOGF("rb_draw_line(%d, %d, %d, %d, %d)", x1, y1, x2, y2, color);
186 offset_coords(&x1, &y1);
187 offset_coords(&x2, &y2);
188 rb_color(color); 307 rb_color(color);
189 rb->lcd_drawline(x1, y1, x2, y2); 308 if(settings.no_aa)
309 {
310 offset_coords(&x1, &y1);
311 offset_coords(&x2, &y2);
312 rb->lcd_drawline(x1, y1, x2, y2);
313 }
314 else
315 draw_antialiased_line(x1, y1, x2, y2);
190} 316}
191 317
192/* 318/*
@@ -351,12 +477,15 @@ static void rb_draw_poly(void *handle, int *coords, int npoints,
351 y1 = coords[2 * (i - 1) + 1]; 477 y1 = coords[2 * (i - 1) + 1];
352 x2 = coords[2 * i]; 478 x2 = coords[2 * i];
353 y2 = coords[2 * i + 1]; 479 y2 = coords[2 * i + 1];
354 offset_coords(&x1, &y1); 480 if(settings.no_aa)
355 offset_coords(&x2, &y2); 481 {
356 rb->lcd_drawline(x1, y1, 482 offset_coords(&x1, &y1);
357 x2, y2); 483 offset_coords(&x2, &y2);
358 //rb->lcd_update(); 484 rb->lcd_drawline(x1, y1,
359 //rb->sleep(HZ/2); 485 x2, y2);
486 }
487 else
488 draw_antialiased_line(x1, y1, x2, y2);
360 } 489 }
361 490
362 int x1, y1, x2, y2; 491 int x1, y1, x2, y2;
@@ -364,11 +493,16 @@ static void rb_draw_poly(void *handle, int *coords, int npoints,
364 y1 = coords[1]; 493 y1 = coords[1];
365 x2 = coords[2 * (npoints - 1)]; 494 x2 = coords[2 * (npoints - 1)];
366 y2 = coords[2 * (npoints - 1) + 1]; 495 y2 = coords[2 * (npoints - 1) + 1];
367 offset_coords(&x1, &y1); 496 if(settings.no_aa)
368 offset_coords(&x2, &y2); 497 {
498 offset_coords(&x1, &y1);
499 offset_coords(&x2, &y2);
369 500
370 rb->lcd_drawline(x1, y1, 501 rb->lcd_drawline(x1, y1,
371 x2, y2); 502 x2, y2);
503 }
504 else
505 draw_antialiased_line(x1, y1, x2, y2);
372} 506}
373 507
374static void rb_draw_circle(void *handle, int cx, int cy, int radius, 508static void rb_draw_circle(void *handle, int cx, int cy, int radius,
@@ -394,25 +528,6 @@ struct blitter {
394 struct bitmap bmp; 528 struct bitmap bmp;
395}; 529};
396 530
397static blitter *rb_blitter_new(void *handle, int w, int h)
398{
399 LOGF("rb_blitter_new");
400 blitter *b = snew(blitter);
401 b->bmp.width = w;
402 b->bmp.height = h;
403 b->bmp.data = smalloc(w * h * sizeof(fb_data));
404 b->have_data = false;
405 return b;
406}
407
408static void rb_blitter_free(void *handle, blitter *bl)
409{
410 LOGF("rb_blitter_free");
411 sfree(bl->bmp.data);
412 sfree(bl);
413 return;
414}
415
416/* originally from emcc.c */ 531/* originally from emcc.c */
417static void trim_rect(int *x, int *y, int *w, int *h) 532static void trim_rect(int *x, int *y, int *w, int *h)
418{ 533{
@@ -430,10 +545,10 @@ static void trim_rect(int *x, int *y, int *w, int *h)
430 y1 = *y + *h; 545 y1 = *y + *h;
431 546
432 /* Clip each coordinate at both extremes of the canvas */ 547 /* Clip each coordinate at both extremes of the canvas */
433 x0 = (x0 < 0 ? 0 : x0 > LCD_WIDTH ? LCD_WIDTH : x0); 548 x0 = (x0 < 0 ? 0 : x0 > LCD_WIDTH - 1 ? LCD_WIDTH - 1: x0);
434 x1 = (x1 < 0 ? 0 : x1 > LCD_WIDTH ? LCD_WIDTH : x1); 549 x1 = (x1 < 0 ? 0 : x1 > LCD_WIDTH - 1 ? LCD_WIDTH - 1: x1);
435 y0 = (y0 < 0 ? 0 : y0 > LCD_HEIGHT ? LCD_HEIGHT : y0); 550 y0 = (y0 < 0 ? 0 : y0 > LCD_HEIGHT - 1 ? LCD_HEIGHT - 1: y0);
436 y1 = (y1 < 0 ? 0 : y1 > LCD_HEIGHT ? LCD_HEIGHT : y1); 551 y1 = (y1 < 0 ? 0 : y1 > LCD_HEIGHT - 1 ? LCD_HEIGHT - 1: y1);
437 552
438 /* Transform back into x,y,w,h to return */ 553 /* Transform back into x,y,w,h to return */
439 *x = x0; 554 *x = x0;
@@ -442,6 +557,25 @@ static void trim_rect(int *x, int *y, int *w, int *h)
442 *h = y1 - y0; 557 *h = y1 - y0;
443} 558}
444 559
560static blitter *rb_blitter_new(void *handle, int w, int h)
561{
562 LOGF("rb_blitter_new");
563 blitter *b = snew(blitter);
564 b->bmp.width = w;
565 b->bmp.height = h;
566 b->bmp.data = smalloc(w * h * sizeof(fb_data));
567 b->have_data = false;
568 return b;
569}
570
571static void rb_blitter_free(void *handle, blitter *bl)
572{
573 LOGF("rb_blitter_free");
574 sfree(bl->bmp.data);
575 sfree(bl);
576 return;
577}
578
445/* copy a section of the framebuffer */ 579/* copy a section of the framebuffer */
446static void rb_blitter_save(void *handle, blitter *bl, int x, int y) 580static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
447{ 581{
@@ -623,8 +757,6 @@ void get_random_seed(void **randseed, int *randseedsize)
623 *randseed = snew(long); 757 *randseed = snew(long);
624 long seed = *rb->current_tick; 758 long seed = *rb->current_tick;
625 rb->memcpy(*randseed, &seed, sizeof(seed)); 759 rb->memcpy(*randseed, &seed, sizeof(seed));
626 //*(long*)*randseed = 42; // debug
627 //rb->splash(HZ, "DEBUG SEED ON");
628 *randseedsize = sizeof(long); 760 *randseedsize = sizeof(long);
629} 761}
630 762
@@ -737,11 +869,13 @@ const char *config_formatter(int sel, void *data, char *buf, size_t len)
737 return buf; 869 return buf;
738} 870}
739 871
740static void config_menu(void) 872static bool config_menu(void)
741{ 873{
742 char *title; 874 char *title;
743 config_item *config = midend_get_config(me, CFG_SETTINGS, &title); 875 config_item *config = midend_get_config(me, CFG_SETTINGS, &title);
744 876
877 bool success = false;
878
745 if(!config) 879 if(!config)
746 { 880 {
747 rb->splash(HZ, "Nothing to configure."); 881 rb->splash(HZ, "Nothing to configure.");
@@ -799,6 +933,10 @@ static void config_menu(void)
799 /* success, and we duplicated the old string, so free it */ 933 /* success, and we duplicated the old string, so free it */
800 sfree(old_str); 934 sfree(old_str);
801 } 935 }
936 else
937 {
938 success = true;
939 }
802 break; 940 break;
803 } 941 }
804 case ACTION_STD_PREV: 942 case ACTION_STD_PREV:
@@ -813,6 +951,7 @@ static void config_menu(void)
813done: 951done:
814 sfree(title); 952 sfree(title);
815 free_cfg(config); 953 free_cfg(config);
954 return success;
816} 955}
817 956
818const char *preset_formatter(int sel, void *data, char *buf, size_t len) 957const char *preset_formatter(int sel, void *data, char *buf, size_t len)
@@ -824,12 +963,12 @@ const char *preset_formatter(int sel, void *data, char *buf, size_t len)
824 return buf; 963 return buf;
825} 964}
826 965
827static void presets_menu(void) 966static bool presets_menu(void)
828{ 967{
829 if(!midend_num_presets(me)) 968 if(!midend_num_presets(me))
830 { 969 {
831 rb->splash(HZ, "No presets!"); 970 rb->splash(HZ, "No presets!");
832 return; 971 return false;
833 } 972 }
834 973
835 /* display a list */ 974 /* display a list */
@@ -843,9 +982,8 @@ static void presets_menu(void)
843 int current = midend_which_preset(me); 982 int current = midend_which_preset(me);
844 rb->gui_synclist_select_item(&list, current >= 0 ? current : 0); 983 rb->gui_synclist_select_item(&list, current >= 0 ? current : 0);
845 984
846 bool done = false;
847 rb->gui_synclist_set_title(&list, "Game Type", NOICON); 985 rb->gui_synclist_set_title(&list, "Game Type", NOICON);
848 while (!done) 986 while(1)
849 { 987 {
850 rb->gui_synclist_draw(&list); 988 rb->gui_synclist_draw(&list);
851 int button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK); 989 int button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
@@ -860,13 +998,11 @@ static void presets_menu(void)
860 game_params *params; 998 game_params *params;
861 midend_fetch_preset(me, sel, &junk, &params); 999 midend_fetch_preset(me, sel, &junk, &params);
862 midend_set_params(me, params); 1000 midend_set_params(me, params);
863 done = true; 1001 return true;
864 break;
865 } 1002 }
866 case ACTION_STD_PREV: 1003 case ACTION_STD_PREV:
867 case ACTION_STD_CANCEL: 1004 case ACTION_STD_CANCEL:
868 done = true; 1005 return false;
869 break;
870 default: 1006 default:
871 break; 1007 break;
872 } 1008 }
@@ -948,6 +1084,37 @@ static void init_default_settings(void)
948 settings.slowmo_factor = 1; 1084 settings.slowmo_factor = 1;
949 settings.bulk = false; 1085 settings.bulk = false;
950 settings.timerflash = false; 1086 settings.timerflash = false;
1087 settings.clipoff = false;
1088 settings.shortcuts = false;
1089 settings.no_aa = false;
1090}
1091
1092static void bench_aa(void)
1093{
1094 rb->sleep(0);
1095#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1096 rb->cpu_boost(true);
1097#endif
1098 int next = *rb->current_tick + HZ;
1099 int i = 0;
1100 while(*rb->current_tick < next)
1101 {
1102 draw_antialiased_line(0, 0, 20, 31);
1103 ++i;
1104 }
1105 rb->splashf(HZ, "%d AA lines/sec", i);
1106 next = *rb->current_tick + HZ;
1107 int j = 0;
1108 while(*rb->current_tick < next)
1109 {
1110 rb->lcd_drawline(0, 0, 20, 31);
1111 ++j;
1112 }
1113 rb->splashf(HZ, "%d normal lines/sec", j);
1114 rb->splashf(HZ, "Efficiency: %d%%", 100 * i / j);
1115#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1116 rb->cpu_boost(false);
1117#endif
951} 1118}
952 1119
953static void debug_menu(void) 1120static void debug_menu(void)
@@ -958,6 +1125,9 @@ static void debug_menu(void)
958 "Toggle bulk update", 1125 "Toggle bulk update",
959 "Toggle flash pixel on timer", 1126 "Toggle flash pixel on timer",
960 "Toggle clip", 1127 "Toggle clip",
1128 "Toggle shortcuts",
1129 "Toggle antialias",
1130 "Benchmark antialias",
961 "Back"); 1131 "Back");
962 bool quit = false; 1132 bool quit = false;
963 int sel = 0; 1133 int sel = 0;
@@ -988,6 +1158,15 @@ static void debug_menu(void)
988 settings.clipoff = !settings.clipoff; 1158 settings.clipoff = !settings.clipoff;
989 break; 1159 break;
990 case 5: 1160 case 5:
1161 settings.shortcuts = !settings.shortcuts;
1162 break;
1163 case 6:
1164 settings.no_aa = !settings.no_aa;
1165 break;
1166 case 7:
1167 bench_aa();
1168 break;
1169 case 8:
991 default: 1170 default:
992 quit = true; 1171 quit = true;
993 break; 1172 break;
@@ -1055,6 +1234,23 @@ static int pausemenu_cb(int action, const struct menu_item_ex *this_item)
1055 return action; 1234 return action;
1056} 1235}
1057 1236
1237static void clear_and_draw(void)
1238{
1239 rb->lcd_clear_display();
1240 rb->lcd_update();
1241
1242 midend_force_redraw(me);
1243 draw_title();
1244}
1245
1246static void reset_drawing(void)
1247{
1248 rb->lcd_set_viewport(NULL);
1249 rb->lcd_set_backdrop(NULL);
1250 rb->lcd_set_foreground(LCD_BLACK);
1251 rb->lcd_set_background(BG_COLOR);
1252}
1253
1058static int pause_menu(void) 1254static int pause_menu(void)
1059{ 1255{
1060#define static auto 1256#define static auto
@@ -1139,19 +1335,27 @@ static int pause_menu(void)
1139 playback_control(NULL); 1335 playback_control(NULL);
1140 break; 1336 break;
1141 case 9: 1337 case 9:
1142 presets_menu(); 1338 if(presets_menu())
1143 midend_new_game(me); 1339 {
1144 fix_size(); 1340 midend_new_game(me);
1145 quit = true; 1341 fix_size();
1342 reset_drawing();
1343 clear_and_draw();
1344 quit = true;
1345 }
1146 break; 1346 break;
1147 case 10: 1347 case 10:
1148 debug_menu(); 1348 debug_menu();
1149 break; 1349 break;
1150 case 11: 1350 case 11:
1151 config_menu(); 1351 if(config_menu())
1152 midend_new_game(me); 1352 {
1153 fix_size(); 1353 midend_new_game(me);
1154 quit = true; 1354 fix_size();
1355 reset_drawing();
1356 clear_and_draw();
1357 quit = true;
1358 }
1155 break; 1359 break;
1156#ifdef COMBINED 1360#ifdef COMBINED
1157 case 12: 1361 case 12:
@@ -1257,8 +1461,8 @@ static int process_input(int tmo)
1257 } 1461 }
1258 LOGF("accepting event 0x%08x", button); 1462 LOGF("accepting event 0x%08x", button);
1259 } 1463 }
1260 /* not inertia: events fire on presses */ 1464 /* default is to ignore repeats except for untangle */
1261 else 1465 else if(strcmp("Untangle", midend_which_game(me)->name))
1262 { 1466 {
1263 /* start accepting input again after a release */ 1467 /* start accepting input again after a release */
1264 if(!button) 1468 if(!button)
@@ -1267,6 +1471,7 @@ static int process_input(int tmo)
1267 return 0; 1471 return 0;
1268 } 1472 }
1269 /* ignore repeats */ 1473 /* ignore repeats */
1474 /* Untangle gets special treatment */
1270 if(!accept_input) 1475 if(!accept_input)
1271 return 0; 1476 return 0;
1272 accept_input = false; 1477 accept_input = false;
@@ -1316,7 +1521,34 @@ static int process_input(int tmo)
1316 case BTN_FIRE: 1521 case BTN_FIRE:
1317 state = CURSOR_SELECT; 1522 state = CURSOR_SELECT;
1318 break; 1523 break;
1524
1525 default:
1526 break;
1319 } 1527 }
1528
1529 if(settings.shortcuts)
1530 {
1531 static bool shortcuts_ok = true;
1532 switch(button)
1533 {
1534 case BTN_LEFT | BTN_FIRE:
1535 if(shortcuts_ok)
1536 midend_process_key(me, 0, 0, 'u');
1537 shortcuts_ok = false;
1538 break;
1539 case BTN_RIGHT | BTN_FIRE:
1540 if(shortcuts_ok)
1541 midend_process_key(me, 0, 0, 'r');
1542 shortcuts_ok = false;
1543 break;
1544 case 0:
1545 shortcuts_ok = true;
1546 break;
1547 default:
1548 break;
1549 }
1550 }
1551
1320 LOGF("process_input done"); 1552 LOGF("process_input done");
1321 LOGF("------------------"); 1553 LOGF("------------------");
1322 return state; 1554 return state;
@@ -1403,13 +1635,23 @@ static void write_wrapper(void *ptr, void *buf, int len)
1403 rb->write(fd, buf, len); 1635 rb->write(fd, buf, len);
1404} 1636}
1405 1637
1406static void clear_and_draw(void) 1638static void init_colors(void)
1407{ 1639{
1408 rb->lcd_clear_display(); 1640 float *floatcolors = midend_colors(me, &ncolors);
1409 rb->lcd_update();
1410 1641
1411 midend_force_redraw(me); 1642 /* convert them to packed RGB */
1412 draw_title(); 1643 colors = smalloc(ncolors * sizeof(unsigned));
1644 unsigned *ptr = colors;
1645 float *floatptr = floatcolors;
1646 for(int i = 0; i < ncolors; ++i)
1647 {
1648 int r = 255 * *(floatptr++);
1649 int g = 255 * *(floatptr++);
1650 int b = 255 * *(floatptr++);
1651 LOGF("color %d is %d %d %d", i, r, g, b);
1652 *ptr++ = LCD_RGBPACK(r, g, b);
1653 }
1654 sfree(floatcolors);
1413} 1655}
1414 1656
1415static char *init_for_game(const game *gm, int load_fd, bool draw) 1657static char *init_for_game(const game *gm, int load_fd, bool draw)
@@ -1431,26 +1673,9 @@ static char *init_for_game(const game *gm, int load_fd, bool draw)
1431 1673
1432 fix_size(); 1674 fix_size();
1433 1675
1434 float *floatcolors = midend_colors(me, &ncolors); 1676 init_colors();
1435
1436 /* convert them to packed RGB */
1437 colors = smalloc(ncolors * sizeof(unsigned));
1438 unsigned *ptr = colors;
1439 float *floatptr = floatcolors;
1440 for(int i = 0; i < ncolors; ++i)
1441 {
1442 int r = 255 * *(floatptr++);
1443 int g = 255 * *(floatptr++);
1444 int b = 255 * *(floatptr++);
1445 LOGF("color %d is %d %d %d", i, r, g, b);
1446 *ptr++ = LCD_RGBPACK(r, g, b);
1447 }
1448 sfree(floatcolors);
1449 1677
1450 rb->lcd_set_viewport(NULL); 1678 reset_drawing();
1451 rb->lcd_set_backdrop(NULL);
1452 rb->lcd_set_foreground(LCD_BLACK);
1453 rb->lcd_set_background(BG_COLOR);
1454 1679
1455 if(draw) 1680 if(draw)
1456 { 1681 {
@@ -1690,22 +1915,26 @@ enum plugin_status plugin_start(const void *param)
1690 playback_control(NULL); 1915 playback_control(NULL);
1691 break; 1916 break;
1692 case 5: 1917 case 5:
1693 presets_menu(); 1918 if(presets_menu())
1694 if(!load_success)
1695 { 1919 {
1920 midend_new_game(me);
1921 fix_size();
1922 init_colors();
1923 reset_drawing();
1696 clear_and_draw(); 1924 clear_and_draw();
1697 goto game_loop; 1925 goto game_loop;
1698 } 1926 }
1699 quit = true;
1700 break; 1927 break;
1701 case 6: 1928 case 6:
1702 config_menu(); 1929 if(config_menu())
1703 if(!load_success)
1704 { 1930 {
1931 midend_new_game(me);
1932 fix_size();
1933 init_colors();
1934 reset_drawing();
1705 clear_and_draw(); 1935 clear_and_draw();
1706 goto game_loop; 1936 goto game_loop;
1707 } 1937 }
1708 quit = true;
1709 break; 1938 break;
1710 case 8: 1939 case 8:
1711 if(load_success) 1940 if(load_success)
diff --git a/apps/plugins/puzzles/untangle.c b/apps/plugins/puzzles/untangle.c
index 839013809b..d46afcbe66 100644
--- a/apps/plugins/puzzles/untangle.c
+++ b/apps/plugins/puzzles/untangle.c
@@ -1162,18 +1162,17 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1162 { 1162 {
1163 if(ui->dragpoint < 0) 1163 if(ui->dragpoint < 0)
1164 { 1164 {
1165 if(ui->cursorpoint < 0)
1166 {
1167 ui->cursorpoint = 0;
1168 return "";
1169 }
1170
1171 /* We're selecting a point here. */ 1165 /* We're selecting a point here. */
1172 /* Search all the points and find the closest one (2-D) in 1166 /* Search all the points and find the closest one (2-D) in
1173 * the given direction. */ 1167 * the given direction. */
1174 int i, best; 1168 int i, best;
1175 long bestd; 1169 long bestd;
1176 1170
1171 if(ui->cursorpoint < 0)
1172 {
1173 ui->cursorpoint = 0;
1174 }
1175
1177 /* 1176 /*
1178 * Begin drag. We drag the vertex _nearest_ to the pointer, 1177 * Begin drag. We drag the vertex _nearest_ to the pointer,
1179 * just in case one is nearly on top of another and we want 1178 * just in case one is nearly on top of another and we want
@@ -1196,7 +1195,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1196 /* Figure out if this point falls into a 90 degree 1195 /* Figure out if this point falls into a 90 degree
1197 * range extending from the current point */ 1196 * range extending from the current point */
1198 1197
1199 float angle = atan2(-dy, dx); /* adjust for raster coordinates */ 1198 float angle = atan2(-dy, dx); /* negate y to adjust for raster coordinates */
1200 1199
1201 /* offset to [0..2*PI] */ 1200 /* offset to [0..2*PI] */
1202 if(angle < 0) 1201 if(angle < 0)
@@ -1494,6 +1493,8 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
1494 ds->bg = bg; 1493 ds->bg = bg;
1495 1494
1496 game_compute_size(&state->params, ds->tilesize, &w, &h); 1495 game_compute_size(&state->params, ds->tilesize, &w, &h);
1496
1497 clip(dr, 0, 0, w, h);
1497 draw_rect(dr, 0, 0, w, h, bg); 1498 draw_rect(dr, 0, 0, w, h, bg);
1498 1499
1499 /* 1500 /*