diff options
Diffstat (limited to 'apps/plugins/puzzles')
-rw-r--r-- | apps/plugins/puzzles/puzzles.make | 4 | ||||
-rw-r--r-- | apps/plugins/puzzles/rockbox.c | 411 | ||||
-rw-r--r-- | apps/plugins/puzzles/untangle.c | 15 |
3 files changed, 319 insertions, 111 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..2884e4e775 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,129 @@ 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 | r2 = RGB_UNPACK_RED(orig); | ||
207 | g2 = RGB_UNPACK_GREEN(orig); | ||
208 | b2 = RGB_UNPACK_BLUE(orig); | ||
209 | |||
210 | unsigned long r, g, b; | ||
211 | r = ((r1 * a) + (r2 * (256 - a))) >> 8; | ||
212 | g = ((g1 * a) + (g2 * (256 - a))) >> 8; | ||
213 | b = ((b1 * a) + (b2 * (256 - a))) >> 8; | ||
214 | |||
215 | *ptr = LCD_RGBPACK(r, g, b); | ||
216 | } | ||
217 | |||
218 | #undef ABS | ||
219 | #define ABS(a) ((a)<0?-(a):(a)) | ||
220 | |||
221 | /* speed benchmark: 34392 lines/sec vs 112687 non-antialiased | ||
222 | * lines/sec at full optimization on ipod6g */ | ||
223 | |||
224 | /* expects UN-OFFSET coordinates, directly access framebuffer */ | ||
225 | static void draw_antialiased_line(int x0, int y0, int x1, int y1) | ||
226 | { | ||
227 | /* fixed-point Wu's algorithm, modified for integer-only endpoints */ | ||
228 | |||
229 | /* passed to plot() to avoid re-calculation */ | ||
230 | unsigned short l = 0, r = LCD_WIDTH, u = 0, d = LCD_HEIGHT; | ||
231 | if(clipped) | ||
232 | { | ||
233 | l = clip_rect.x; | ||
234 | r = clip_rect.x + clip_rect.width; | ||
235 | u = clip_rect.y; | ||
236 | d = clip_rect.y + clip_rect.height; | ||
237 | } | ||
238 | |||
239 | bool steep = ABS(y1 - y0) > ABS(x1 - x0); | ||
240 | int tmp; | ||
241 | if(steep) | ||
242 | { | ||
243 | SWAP(x0, y0, tmp); | ||
244 | SWAP(x1, y1, tmp); | ||
245 | } | ||
246 | if(x0 > x1) | ||
247 | { | ||
248 | SWAP(x0, x1, tmp); | ||
249 | SWAP(y0, y1, tmp); | ||
250 | } | ||
251 | |||
252 | int dx, dy; | ||
253 | dx = x1 - x0; | ||
254 | dy = y1 - y0; | ||
255 | |||
256 | if(!(dx << FRACBITS)) | ||
257 | return; /* bail out */ | ||
258 | |||
259 | long gradient = fp_div(dy << FRACBITS, dx << FRACBITS, FRACBITS); | ||
260 | long intery = (y0 << FRACBITS); | ||
261 | |||
262 | unsigned color = rb->lcd_get_foreground(); | ||
263 | unsigned long r1, g1, b1; | ||
264 | r1 = RGB_UNPACK_RED(color); | ||
265 | g1 = RGB_UNPACK_GREEN(color); | ||
266 | b1 = RGB_UNPACK_BLUE(color); | ||
267 | |||
268 | /* main loop */ | ||
269 | if(steep) | ||
270 | { | ||
271 | for(int x = x0; x <= x1; ++x, intery += gradient) | ||
272 | { | ||
273 | unsigned y = intery >> FRACBITS; | ||
274 | unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8); | ||
275 | |||
276 | plot(y, x, (1 << 8) - alpha, r1, g1, b1, l, r, u, d); | ||
277 | plot(y + 1, x, alpha, r1, g1, b1, l, r, u, d); | ||
278 | } | ||
279 | } | ||
280 | else | ||
281 | { | ||
282 | for(int x = x0; x <= x1; ++x, intery += gradient) | ||
283 | { | ||
284 | unsigned y = intery >> FRACBITS; | ||
285 | unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8); | ||
286 | |||
287 | plot(x, y, (1 << 8) - alpha, r1, g1, b1, l, r, u, d); | ||
288 | plot(x, y + 1, alpha, r1, g1, b1, l, r, u, d); | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | |||
182 | static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2, | 293 | static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2, |
183 | int color) | 294 | int color) |
184 | { | 295 | { |
185 | LOGF("rb_draw_line(%d, %d, %d, %d, %d)", x1, y1, x2, y2, color); | 296 | 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); | 297 | rb_color(color); |
189 | rb->lcd_drawline(x1, y1, x2, y2); | 298 | if(settings.no_aa) |
299 | { | ||
300 | offset_coords(&x1, &y1); | ||
301 | offset_coords(&x2, &y2); | ||
302 | rb->lcd_drawline(x1, y1, x2, y2); | ||
303 | } | ||
304 | else | ||
305 | draw_antialiased_line(x1, y1, x2, y2); | ||
190 | } | 306 | } |
191 | 307 | ||
192 | /* | 308 | /* |
@@ -351,12 +467,15 @@ static void rb_draw_poly(void *handle, int *coords, int npoints, | |||
351 | y1 = coords[2 * (i - 1) + 1]; | 467 | y1 = coords[2 * (i - 1) + 1]; |
352 | x2 = coords[2 * i]; | 468 | x2 = coords[2 * i]; |
353 | y2 = coords[2 * i + 1]; | 469 | y2 = coords[2 * i + 1]; |
354 | offset_coords(&x1, &y1); | 470 | if(settings.no_aa) |
355 | offset_coords(&x2, &y2); | 471 | { |
356 | rb->lcd_drawline(x1, y1, | 472 | offset_coords(&x1, &y1); |
357 | x2, y2); | 473 | offset_coords(&x2, &y2); |
358 | //rb->lcd_update(); | 474 | rb->lcd_drawline(x1, y1, |
359 | //rb->sleep(HZ/2); | 475 | x2, y2); |
476 | } | ||
477 | else | ||
478 | draw_antialiased_line(x1, y1, x2, y2); | ||
360 | } | 479 | } |
361 | 480 | ||
362 | int x1, y1, x2, y2; | 481 | int x1, y1, x2, y2; |
@@ -364,11 +483,16 @@ static void rb_draw_poly(void *handle, int *coords, int npoints, | |||
364 | y1 = coords[1]; | 483 | y1 = coords[1]; |
365 | x2 = coords[2 * (npoints - 1)]; | 484 | x2 = coords[2 * (npoints - 1)]; |
366 | y2 = coords[2 * (npoints - 1) + 1]; | 485 | y2 = coords[2 * (npoints - 1) + 1]; |
367 | offset_coords(&x1, &y1); | 486 | if(settings.no_aa) |
368 | offset_coords(&x2, &y2); | 487 | { |
488 | offset_coords(&x1, &y1); | ||
489 | offset_coords(&x2, &y2); | ||
369 | 490 | ||
370 | rb->lcd_drawline(x1, y1, | 491 | rb->lcd_drawline(x1, y1, |
371 | x2, y2); | 492 | x2, y2); |
493 | } | ||
494 | else | ||
495 | draw_antialiased_line(x1, y1, x2, y2); | ||
372 | } | 496 | } |
373 | 497 | ||
374 | static void rb_draw_circle(void *handle, int cx, int cy, int radius, | 498 | static void rb_draw_circle(void *handle, int cx, int cy, int radius, |
@@ -394,25 +518,6 @@ struct blitter { | |||
394 | struct bitmap bmp; | 518 | struct bitmap bmp; |
395 | }; | 519 | }; |
396 | 520 | ||
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 */ | 521 | /* originally from emcc.c */ |
417 | static void trim_rect(int *x, int *y, int *w, int *h) | 522 | static void trim_rect(int *x, int *y, int *w, int *h) |
418 | { | 523 | { |
@@ -430,10 +535,10 @@ static void trim_rect(int *x, int *y, int *w, int *h) | |||
430 | y1 = *y + *h; | 535 | y1 = *y + *h; |
431 | 536 | ||
432 | /* Clip each coordinate at both extremes of the canvas */ | 537 | /* Clip each coordinate at both extremes of the canvas */ |
433 | x0 = (x0 < 0 ? 0 : x0 > LCD_WIDTH ? LCD_WIDTH : x0); | 538 | x0 = (x0 < 0 ? 0 : x0 > LCD_WIDTH - 1 ? LCD_WIDTH - 1: x0); |
434 | x1 = (x1 < 0 ? 0 : x1 > LCD_WIDTH ? LCD_WIDTH : x1); | 539 | x1 = (x1 < 0 ? 0 : x1 > LCD_WIDTH - 1 ? LCD_WIDTH - 1: x1); |
435 | y0 = (y0 < 0 ? 0 : y0 > LCD_HEIGHT ? LCD_HEIGHT : y0); | 540 | y0 = (y0 < 0 ? 0 : y0 > LCD_HEIGHT - 1 ? LCD_HEIGHT - 1: y0); |
436 | y1 = (y1 < 0 ? 0 : y1 > LCD_HEIGHT ? LCD_HEIGHT : y1); | 541 | y1 = (y1 < 0 ? 0 : y1 > LCD_HEIGHT - 1 ? LCD_HEIGHT - 1: y1); |
437 | 542 | ||
438 | /* Transform back into x,y,w,h to return */ | 543 | /* Transform back into x,y,w,h to return */ |
439 | *x = x0; | 544 | *x = x0; |
@@ -442,6 +547,25 @@ static void trim_rect(int *x, int *y, int *w, int *h) | |||
442 | *h = y1 - y0; | 547 | *h = y1 - y0; |
443 | } | 548 | } |
444 | 549 | ||
550 | static blitter *rb_blitter_new(void *handle, int w, int h) | ||
551 | { | ||
552 | LOGF("rb_blitter_new"); | ||
553 | blitter *b = snew(blitter); | ||
554 | b->bmp.width = w; | ||
555 | b->bmp.height = h; | ||
556 | b->bmp.data = smalloc(w * h * sizeof(fb_data)); | ||
557 | b->have_data = false; | ||
558 | return b; | ||
559 | } | ||
560 | |||
561 | static void rb_blitter_free(void *handle, blitter *bl) | ||
562 | { | ||
563 | LOGF("rb_blitter_free"); | ||
564 | sfree(bl->bmp.data); | ||
565 | sfree(bl); | ||
566 | return; | ||
567 | } | ||
568 | |||
445 | /* copy a section of the framebuffer */ | 569 | /* copy a section of the framebuffer */ |
446 | static void rb_blitter_save(void *handle, blitter *bl, int x, int y) | 570 | static void rb_blitter_save(void *handle, blitter *bl, int x, int y) |
447 | { | 571 | { |
@@ -623,8 +747,6 @@ void get_random_seed(void **randseed, int *randseedsize) | |||
623 | *randseed = snew(long); | 747 | *randseed = snew(long); |
624 | long seed = *rb->current_tick; | 748 | long seed = *rb->current_tick; |
625 | rb->memcpy(*randseed, &seed, sizeof(seed)); | 749 | rb->memcpy(*randseed, &seed, sizeof(seed)); |
626 | //*(long*)*randseed = 42; // debug | ||
627 | //rb->splash(HZ, "DEBUG SEED ON"); | ||
628 | *randseedsize = sizeof(long); | 750 | *randseedsize = sizeof(long); |
629 | } | 751 | } |
630 | 752 | ||
@@ -683,8 +805,7 @@ static int list_choose(const char *list_str, const char *title) | |||
683 | } | 805 | } |
684 | } | 806 | } |
685 | 807 | ||
686 | /* return value is only meaningful when type == C_STRING */ | 808 | static void do_configure_item(config_item *cfg) |
687 | static bool do_configure_item(config_item *cfg) | ||
688 | { | 809 | { |
689 | switch(cfg->type) | 810 | switch(cfg->type) |
690 | { | 811 | { |
@@ -698,11 +819,11 @@ static bool do_configure_item(config_item *cfg) | |||
698 | if(rb->kbd_input(newstr, MAX_STRLEN) < 0) | 819 | if(rb->kbd_input(newstr, MAX_STRLEN) < 0) |
699 | { | 820 | { |
700 | sfree(newstr); | 821 | sfree(newstr); |
701 | return false; | 822 | break; |
702 | } | 823 | } |
703 | sfree(cfg->sval); | 824 | sfree(cfg->sval); |
704 | cfg->sval = newstr; | 825 | cfg->sval = newstr; |
705 | return true; | 826 | break; |
706 | } | 827 | } |
707 | case C_BOOLEAN: | 828 | case C_BOOLEAN: |
708 | { | 829 | { |
@@ -726,7 +847,6 @@ static bool do_configure_item(config_item *cfg) | |||
726 | fatal("bad type"); | 847 | fatal("bad type"); |
727 | break; | 848 | break; |
728 | } | 849 | } |
729 | return false; | ||
730 | } | 850 | } |
731 | 851 | ||
732 | const char *config_formatter(int sel, void *data, char *buf, size_t len) | 852 | const char *config_formatter(int sel, void *data, char *buf, size_t len) |
@@ -737,11 +857,13 @@ const char *config_formatter(int sel, void *data, char *buf, size_t len) | |||
737 | return buf; | 857 | return buf; |
738 | } | 858 | } |
739 | 859 | ||
740 | static void config_menu(void) | 860 | static bool config_menu(void) |
741 | { | 861 | { |
742 | char *title; | 862 | char *title; |
743 | config_item *config = midend_get_config(me, CFG_SETTINGS, &title); | 863 | config_item *config = midend_get_config(me, CFG_SETTINGS, &title); |
744 | 864 | ||
865 | bool success = false; | ||
866 | |||
745 | if(!config) | 867 | if(!config) |
746 | { | 868 | { |
747 | rb->splash(HZ, "Nothing to configure."); | 869 | rb->splash(HZ, "Nothing to configure."); |
@@ -782,22 +904,16 @@ static void config_menu(void) | |||
782 | config_item old; | 904 | config_item old; |
783 | int pos = rb->gui_synclist_get_sel_pos(&list); | 905 | int pos = rb->gui_synclist_get_sel_pos(&list); |
784 | memcpy(&old, config + pos, sizeof(old)); | 906 | memcpy(&old, config + pos, sizeof(old)); |
785 | char *old_str; | 907 | do_configure_item(config + pos); |
786 | if(old.type == C_STRING) | ||
787 | old_str = dupstr(old.sval); | ||
788 | bool freed_str = do_configure_item(config + pos); | ||
789 | char *err = midend_set_config(me, CFG_SETTINGS, config); | 908 | char *err = midend_set_config(me, CFG_SETTINGS, config); |
790 | if(err) | 909 | if(err) |
791 | { | 910 | { |
792 | rb->splash(HZ, err); | 911 | rb->splash(HZ, err); |
793 | memcpy(config + pos, &old, sizeof(old)); | 912 | memcpy(config + pos, &old, sizeof(old)); |
794 | if(freed_str) | ||
795 | config[pos].sval = old_str; | ||
796 | } | 913 | } |
797 | else if(old.type == C_STRING) | 914 | else |
798 | { | 915 | { |
799 | /* success, and we duplicated the old string, so free it */ | 916 | success = true; |
800 | sfree(old_str); | ||
801 | } | 917 | } |
802 | break; | 918 | break; |
803 | } | 919 | } |
@@ -813,6 +929,7 @@ static void config_menu(void) | |||
813 | done: | 929 | done: |
814 | sfree(title); | 930 | sfree(title); |
815 | free_cfg(config); | 931 | free_cfg(config); |
932 | return success; | ||
816 | } | 933 | } |
817 | 934 | ||
818 | const char *preset_formatter(int sel, void *data, char *buf, size_t len) | 935 | const char *preset_formatter(int sel, void *data, char *buf, size_t len) |
@@ -824,12 +941,12 @@ const char *preset_formatter(int sel, void *data, char *buf, size_t len) | |||
824 | return buf; | 941 | return buf; |
825 | } | 942 | } |
826 | 943 | ||
827 | static void presets_menu(void) | 944 | static bool presets_menu(void) |
828 | { | 945 | { |
829 | if(!midend_num_presets(me)) | 946 | if(!midend_num_presets(me)) |
830 | { | 947 | { |
831 | rb->splash(HZ, "No presets!"); | 948 | rb->splash(HZ, "No presets!"); |
832 | return; | 949 | return false; |
833 | } | 950 | } |
834 | 951 | ||
835 | /* display a list */ | 952 | /* display a list */ |
@@ -843,9 +960,8 @@ static void presets_menu(void) | |||
843 | int current = midend_which_preset(me); | 960 | int current = midend_which_preset(me); |
844 | rb->gui_synclist_select_item(&list, current >= 0 ? current : 0); | 961 | rb->gui_synclist_select_item(&list, current >= 0 ? current : 0); |
845 | 962 | ||
846 | bool done = false; | ||
847 | rb->gui_synclist_set_title(&list, "Game Type", NOICON); | 963 | rb->gui_synclist_set_title(&list, "Game Type", NOICON); |
848 | while (!done) | 964 | while(1) |
849 | { | 965 | { |
850 | rb->gui_synclist_draw(&list); | 966 | rb->gui_synclist_draw(&list); |
851 | int button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK); | 967 | int button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK); |
@@ -860,13 +976,11 @@ static void presets_menu(void) | |||
860 | game_params *params; | 976 | game_params *params; |
861 | midend_fetch_preset(me, sel, &junk, ¶ms); | 977 | midend_fetch_preset(me, sel, &junk, ¶ms); |
862 | midend_set_params(me, params); | 978 | midend_set_params(me, params); |
863 | done = true; | 979 | return true; |
864 | break; | ||
865 | } | 980 | } |
866 | case ACTION_STD_PREV: | 981 | case ACTION_STD_PREV: |
867 | case ACTION_STD_CANCEL: | 982 | case ACTION_STD_CANCEL: |
868 | done = true; | 983 | return false; |
869 | break; | ||
870 | default: | 984 | default: |
871 | break; | 985 | break; |
872 | } | 986 | } |
@@ -948,6 +1062,37 @@ static void init_default_settings(void) | |||
948 | settings.slowmo_factor = 1; | 1062 | settings.slowmo_factor = 1; |
949 | settings.bulk = false; | 1063 | settings.bulk = false; |
950 | settings.timerflash = false; | 1064 | settings.timerflash = false; |
1065 | settings.clipoff = false; | ||
1066 | settings.shortcuts = false; | ||
1067 | settings.no_aa = false; | ||
1068 | } | ||
1069 | |||
1070 | static void bench_aa(void) | ||
1071 | { | ||
1072 | rb->sleep(0); | ||
1073 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
1074 | rb->cpu_boost(true); | ||
1075 | #endif | ||
1076 | int next = *rb->current_tick + HZ; | ||
1077 | int i = 0; | ||
1078 | while(*rb->current_tick < next) | ||
1079 | { | ||
1080 | draw_antialiased_line(0, 0, 20, 31); | ||
1081 | ++i; | ||
1082 | } | ||
1083 | rb->splashf(HZ, "%d AA lines/sec", i); | ||
1084 | next = *rb->current_tick + HZ; | ||
1085 | int j = 0; | ||
1086 | while(*rb->current_tick < next) | ||
1087 | { | ||
1088 | rb->lcd_drawline(0, 0, 20, 31); | ||
1089 | ++j; | ||
1090 | } | ||
1091 | rb->splashf(HZ, "%d normal lines/sec", j); | ||
1092 | rb->splashf(HZ, "Efficiency: %d%%", 100 * i / j); | ||
1093 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
1094 | rb->cpu_boost(false); | ||
1095 | #endif | ||
951 | } | 1096 | } |
952 | 1097 | ||
953 | static void debug_menu(void) | 1098 | static void debug_menu(void) |
@@ -958,6 +1103,9 @@ static void debug_menu(void) | |||
958 | "Toggle bulk update", | 1103 | "Toggle bulk update", |
959 | "Toggle flash pixel on timer", | 1104 | "Toggle flash pixel on timer", |
960 | "Toggle clip", | 1105 | "Toggle clip", |
1106 | "Toggle shortcuts", | ||
1107 | "Toggle antialias", | ||
1108 | "Benchmark antialias", | ||
961 | "Back"); | 1109 | "Back"); |
962 | bool quit = false; | 1110 | bool quit = false; |
963 | int sel = 0; | 1111 | int sel = 0; |
@@ -988,6 +1136,15 @@ static void debug_menu(void) | |||
988 | settings.clipoff = !settings.clipoff; | 1136 | settings.clipoff = !settings.clipoff; |
989 | break; | 1137 | break; |
990 | case 5: | 1138 | case 5: |
1139 | settings.shortcuts = !settings.shortcuts; | ||
1140 | break; | ||
1141 | case 6: | ||
1142 | settings.no_aa = !settings.no_aa; | ||
1143 | break; | ||
1144 | case 7: | ||
1145 | bench_aa(); | ||
1146 | break; | ||
1147 | case 8: | ||
991 | default: | 1148 | default: |
992 | quit = true; | 1149 | quit = true; |
993 | break; | 1150 | break; |
@@ -1055,6 +1212,23 @@ static int pausemenu_cb(int action, const struct menu_item_ex *this_item) | |||
1055 | return action; | 1212 | return action; |
1056 | } | 1213 | } |
1057 | 1214 | ||
1215 | static void clear_and_draw(void) | ||
1216 | { | ||
1217 | rb->lcd_clear_display(); | ||
1218 | rb->lcd_update(); | ||
1219 | |||
1220 | midend_force_redraw(me); | ||
1221 | draw_title(); | ||
1222 | } | ||
1223 | |||
1224 | static void reset_drawing(void) | ||
1225 | { | ||
1226 | rb->lcd_set_viewport(NULL); | ||
1227 | rb->lcd_set_backdrop(NULL); | ||
1228 | rb->lcd_set_foreground(LCD_BLACK); | ||
1229 | rb->lcd_set_background(BG_COLOR); | ||
1230 | } | ||
1231 | |||
1058 | static int pause_menu(void) | 1232 | static int pause_menu(void) |
1059 | { | 1233 | { |
1060 | #define static auto | 1234 | #define static auto |
@@ -1139,19 +1313,27 @@ static int pause_menu(void) | |||
1139 | playback_control(NULL); | 1313 | playback_control(NULL); |
1140 | break; | 1314 | break; |
1141 | case 9: | 1315 | case 9: |
1142 | presets_menu(); | 1316 | if(presets_menu()) |
1143 | midend_new_game(me); | 1317 | { |
1144 | fix_size(); | 1318 | midend_new_game(me); |
1145 | quit = true; | 1319 | fix_size(); |
1320 | reset_drawing(); | ||
1321 | clear_and_draw(); | ||
1322 | quit = true; | ||
1323 | } | ||
1146 | break; | 1324 | break; |
1147 | case 10: | 1325 | case 10: |
1148 | debug_menu(); | 1326 | debug_menu(); |
1149 | break; | 1327 | break; |
1150 | case 11: | 1328 | case 11: |
1151 | config_menu(); | 1329 | if(config_menu()) |
1152 | midend_new_game(me); | 1330 | { |
1153 | fix_size(); | 1331 | midend_new_game(me); |
1154 | quit = true; | 1332 | fix_size(); |
1333 | reset_drawing(); | ||
1334 | clear_and_draw(); | ||
1335 | quit = true; | ||
1336 | } | ||
1155 | break; | 1337 | break; |
1156 | #ifdef COMBINED | 1338 | #ifdef COMBINED |
1157 | case 12: | 1339 | case 12: |
@@ -1257,8 +1439,8 @@ static int process_input(int tmo) | |||
1257 | } | 1439 | } |
1258 | LOGF("accepting event 0x%08x", button); | 1440 | LOGF("accepting event 0x%08x", button); |
1259 | } | 1441 | } |
1260 | /* not inertia: events fire on presses */ | 1442 | /* default is to ignore repeats except for untangle */ |
1261 | else | 1443 | else if(strcmp("Untangle", midend_which_game(me)->name)) |
1262 | { | 1444 | { |
1263 | /* start accepting input again after a release */ | 1445 | /* start accepting input again after a release */ |
1264 | if(!button) | 1446 | if(!button) |
@@ -1267,6 +1449,7 @@ static int process_input(int tmo) | |||
1267 | return 0; | 1449 | return 0; |
1268 | } | 1450 | } |
1269 | /* ignore repeats */ | 1451 | /* ignore repeats */ |
1452 | /* Untangle gets special treatment */ | ||
1270 | if(!accept_input) | 1453 | if(!accept_input) |
1271 | return 0; | 1454 | return 0; |
1272 | accept_input = false; | 1455 | accept_input = false; |
@@ -1316,7 +1499,34 @@ static int process_input(int tmo) | |||
1316 | case BTN_FIRE: | 1499 | case BTN_FIRE: |
1317 | state = CURSOR_SELECT; | 1500 | state = CURSOR_SELECT; |
1318 | break; | 1501 | break; |
1502 | |||
1503 | default: | ||
1504 | break; | ||
1319 | } | 1505 | } |
1506 | |||
1507 | if(settings.shortcuts) | ||
1508 | { | ||
1509 | static bool shortcuts_ok = true; | ||
1510 | switch(button) | ||
1511 | { | ||
1512 | case BTN_LEFT | BTN_FIRE: | ||
1513 | if(shortcuts_ok) | ||
1514 | midend_process_key(me, 0, 0, 'u'); | ||
1515 | shortcuts_ok = false; | ||
1516 | break; | ||
1517 | case BTN_RIGHT | BTN_FIRE: | ||
1518 | if(shortcuts_ok) | ||
1519 | midend_process_key(me, 0, 0, 'r'); | ||
1520 | shortcuts_ok = false; | ||
1521 | break; | ||
1522 | case 0: | ||
1523 | shortcuts_ok = true; | ||
1524 | break; | ||
1525 | default: | ||
1526 | break; | ||
1527 | } | ||
1528 | } | ||
1529 | |||
1320 | LOGF("process_input done"); | 1530 | LOGF("process_input done"); |
1321 | LOGF("------------------"); | 1531 | LOGF("------------------"); |
1322 | return state; | 1532 | return state; |
@@ -1403,13 +1613,23 @@ static void write_wrapper(void *ptr, void *buf, int len) | |||
1403 | rb->write(fd, buf, len); | 1613 | rb->write(fd, buf, len); |
1404 | } | 1614 | } |
1405 | 1615 | ||
1406 | static void clear_and_draw(void) | 1616 | static void init_colors(void) |
1407 | { | 1617 | { |
1408 | rb->lcd_clear_display(); | 1618 | float *floatcolors = midend_colors(me, &ncolors); |
1409 | rb->lcd_update(); | ||
1410 | 1619 | ||
1411 | midend_force_redraw(me); | 1620 | /* convert them to packed RGB */ |
1412 | draw_title(); | 1621 | colors = smalloc(ncolors * sizeof(unsigned)); |
1622 | unsigned *ptr = colors; | ||
1623 | float *floatptr = floatcolors; | ||
1624 | for(int i = 0; i < ncolors; ++i) | ||
1625 | { | ||
1626 | int r = 255 * *(floatptr++); | ||
1627 | int g = 255 * *(floatptr++); | ||
1628 | int b = 255 * *(floatptr++); | ||
1629 | LOGF("color %d is %d %d %d", i, r, g, b); | ||
1630 | *ptr++ = LCD_RGBPACK(r, g, b); | ||
1631 | } | ||
1632 | sfree(floatcolors); | ||
1413 | } | 1633 | } |
1414 | 1634 | ||
1415 | static char *init_for_game(const game *gm, int load_fd, bool draw) | 1635 | static char *init_for_game(const game *gm, int load_fd, bool draw) |
@@ -1431,26 +1651,9 @@ static char *init_for_game(const game *gm, int load_fd, bool draw) | |||
1431 | 1651 | ||
1432 | fix_size(); | 1652 | fix_size(); |
1433 | 1653 | ||
1434 | float *floatcolors = midend_colors(me, &ncolors); | 1654 | init_colors(); |
1435 | 1655 | ||
1436 | /* convert them to packed RGB */ | 1656 | reset_drawing(); |
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 | |||
1450 | rb->lcd_set_viewport(NULL); | ||
1451 | rb->lcd_set_backdrop(NULL); | ||
1452 | rb->lcd_set_foreground(LCD_BLACK); | ||
1453 | rb->lcd_set_background(BG_COLOR); | ||
1454 | 1657 | ||
1455 | if(draw) | 1658 | if(draw) |
1456 | { | 1659 | { |
@@ -1690,22 +1893,26 @@ enum plugin_status plugin_start(const void *param) | |||
1690 | playback_control(NULL); | 1893 | playback_control(NULL); |
1691 | break; | 1894 | break; |
1692 | case 5: | 1895 | case 5: |
1693 | presets_menu(); | 1896 | if(presets_menu()) |
1694 | if(!load_success) | ||
1695 | { | 1897 | { |
1898 | midend_new_game(me); | ||
1899 | fix_size(); | ||
1900 | init_colors(); | ||
1901 | reset_drawing(); | ||
1696 | clear_and_draw(); | 1902 | clear_and_draw(); |
1697 | goto game_loop; | 1903 | goto game_loop; |
1698 | } | 1904 | } |
1699 | quit = true; | ||
1700 | break; | 1905 | break; |
1701 | case 6: | 1906 | case 6: |
1702 | config_menu(); | 1907 | if(config_menu()) |
1703 | if(!load_success) | ||
1704 | { | 1908 | { |
1909 | midend_new_game(me); | ||
1910 | fix_size(); | ||
1911 | init_colors(); | ||
1912 | reset_drawing(); | ||
1705 | clear_and_draw(); | 1913 | clear_and_draw(); |
1706 | goto game_loop; | 1914 | goto game_loop; |
1707 | } | 1915 | } |
1708 | quit = true; | ||
1709 | break; | 1916 | break; |
1710 | case 8: | 1917 | case 8: |
1711 | if(load_success) | 1918 | 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 | /* |