diff options
-rw-r--r-- | apps/plugins/puzzles/puzzles.make | 4 | ||||
-rw-r--r-- | apps/plugins/puzzles/rockbox.c | 405 | ||||
-rw-r--r-- | apps/plugins/puzzles/untangle.c | 15 |
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) | |||
43 | endif | 43 | endif |
44 | 44 | ||
45 | # Hack to suppress all warnings: | 45 | # Hack to suppress all warnings: |
46 | PUZZLESFLAGS = $(filter-out -O%,$(PLUGINFLAGS)) -Os \ | 46 | PUZZLESFLAGS = $(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) |
49 | ifdef PUZZLES_COMBINED | 49 | ifdef PUZZLES_COMBINED |
50 | PUZZLESFLAGS += -DCOMBINED | 50 | PUZZLESFLAGS += -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 | ||
76 | static struct settings_t { | 77 | static 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! */ | ||
191 | static 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 */ | ||
235 | static 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 | |||
182 | static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2, | 303 | static 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 | ||
374 | static void rb_draw_circle(void *handle, int cx, int cy, int radius, | 508 | static 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 | ||
397 | static 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 | |||
408 | static 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 */ |
417 | static void trim_rect(int *x, int *y, int *w, int *h) | 532 | static 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 | ||
560 | static 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 | |||
571 | static 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 */ |
446 | static void rb_blitter_save(void *handle, blitter *bl, int x, int y) | 580 | static 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 | ||
740 | static void config_menu(void) | 872 | static 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) | |||
813 | done: | 951 | done: |
814 | sfree(title); | 952 | sfree(title); |
815 | free_cfg(config); | 953 | free_cfg(config); |
954 | return success; | ||
816 | } | 955 | } |
817 | 956 | ||
818 | const char *preset_formatter(int sel, void *data, char *buf, size_t len) | 957 | const 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 | ||
827 | static void presets_menu(void) | 966 | static 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, ¶ms); | 999 | midend_fetch_preset(me, sel, &junk, ¶ms); |
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 | |||
1092 | static 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 | ||
953 | static void debug_menu(void) | 1120 | static 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 | ||
1237 | static 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 | |||
1246 | static 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 | |||
1058 | static int pause_menu(void) | 1254 | static 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 | ||
1406 | static void clear_and_draw(void) | 1638 | static 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 | ||
1415 | static char *init_for_game(const game *gm, int load_fd, bool draw) | 1657 | static 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 | /* |