diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/bitmaps/native/SOURCES | 5 | ||||
-rw-r--r-- | apps/plugins/puzzles/SOURCES.games | 20 | ||||
-rw-r--r-- | apps/plugins/puzzles/rbmalloc.c | 6 | ||||
-rw-r--r-- | apps/plugins/puzzles/rockbox.c | 445 | ||||
-rw-r--r-- | apps/plugins/puzzles/src/LICENCE | 5 | ||||
-rw-r--r-- | apps/plugins/puzzles/src/filling.c | 2 | ||||
-rw-r--r-- | apps/plugins/puzzles/src/grid.c | 96 | ||||
-rw-r--r-- | apps/plugins/puzzles/src/grid.h | 1 | ||||
-rw-r--r-- | apps/plugins/puzzles/src/loopy.c | 3 | ||||
-rw-r--r-- | apps/plugins/puzzles/src/palisade.c | 21 |
10 files changed, 498 insertions, 106 deletions
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES index b6a563d2b0..99297306e7 100644 --- a/apps/plugins/bitmaps/native/SOURCES +++ b/apps/plugins/bitmaps/native/SOURCES | |||
@@ -538,6 +538,11 @@ pegbox_pieces.9x7x1.bmp | |||
538 | #endif | 538 | #endif |
539 | #endif | 539 | #endif |
540 | 540 | ||
541 | /* Puzzles */ | ||
542 | #if defined(HAVE_LCD_COLOR) && \ | ||
543 | (!defined(LCD_STRIDEFORMAT) || (LCD_STRIDEFORMAT != VERTICAL_STRIDE)) | ||
544 | puzzles_cursor.11x16x24.bmp | ||
545 | #endif | ||
541 | 546 | ||
542 | /* Rockblox */ | 547 | /* Rockblox */ |
543 | #if LCD_DEPTH >= 16 /* colour versions*/ | 548 | #if LCD_DEPTH >= 16 /* colour versions*/ |
diff --git a/apps/plugins/puzzles/SOURCES.games b/apps/plugins/puzzles/SOURCES.games index 8893c3e9a4..2fbedae073 100644 --- a/apps/plugins/puzzles/SOURCES.games +++ b/apps/plugins/puzzles/SOURCES.games | |||
@@ -5,21 +5,20 @@ src/bridges.c | |||
5 | src/cube.c | 5 | src/cube.c |
6 | src/dominosa.c | 6 | src/dominosa.c |
7 | src/fifteen.c | 7 | src/fifteen.c |
8 | /*src/filling.c*/ | 8 | //src/filling.c /* requires numeric input */ |
9 | src/flip.c | 9 | src/flip.c |
10 | src/flood.c | 10 | src/flood.c |
11 | src/galaxies.c | 11 | src/galaxies.c |
12 | src/guess.c | 12 | src/guess.c |
13 | src/inertia.c | 13 | src/inertia.c |
14 | /*src/keen.c*/ | 14 | //src/keen.c /* numeric input */ |
15 | src/lightup.c | 15 | src/lightup.c |
16 | /*src/loopy.c*/ | ||
17 | src/magnets.c | 16 | src/magnets.c |
18 | src/map.c | 17 | src/map.c |
19 | src/mines.c | 18 | src/mines.c |
20 | src/net.c | 19 | src/net.c |
21 | src/netslide.c | 20 | src/netslide.c |
22 | /*src/palisade.c*/ | 21 | src/palisade.c |
23 | src/pattern.c | 22 | src/pattern.c |
24 | src/pegs.c | 23 | src/pegs.c |
25 | src/range.c | 24 | src/range.c |
@@ -29,17 +28,16 @@ src/signpost.c | |||
29 | src/singles.c | 28 | src/singles.c |
30 | src/sixteen.c | 29 | src/sixteen.c |
31 | src/slant.c | 30 | src/slant.c |
32 | /*src/solo.c*/ | ||
33 | src/tents.c | 31 | src/tents.c |
34 | /*src/towers.c*/ | 32 | //src/towers.c /* numeric input */ |
35 | src/tracks.c | 33 | src/tracks.c |
36 | src/twiddle.c | 34 | src/twiddle.c |
37 | /*src/undead.c*/ | 35 | //src/undead.c /* keyboard input */ |
38 | /*src/unequal.c*/ | 36 | //src/unequal.c /* numeric input */ |
39 | src/unruly.c | 37 | src/unruly.c |
40 | src/untangle.c | 38 | src/untangle.c |
41 | 39 | ||
42 | /* disabled for now */ | 40 | /* disabled for now (fix puzzles.make and CATEGORIES to accomodate these) */ |
43 | /*src/unfinished/group.c*/ | 41 | /*src/unfinished/group.c*/ |
44 | /*src/unfinished/separate.c*/ | 42 | /*src/unfinished/separate.c*/ |
45 | /*src/unfinished/slide.c*/ | 43 | /*src/unfinished/slide.c*/ |
@@ -48,6 +46,6 @@ src/untangle.c | |||
48 | /* no c200v2 */ | 46 | /* no c200v2 */ |
49 | #if PLUGIN_BUFFER_SIZE > 0x14000 | 47 | #if PLUGIN_BUFFER_SIZE > 0x14000 |
50 | src/pearl.c | 48 | src/pearl.c |
51 | /*src/loopy.c*/ | 49 | src/loopy.c /* mouse input */ |
52 | /*src/solo.c*/ | 50 | //src/solo.c /* numeric input */ |
53 | #endif | 51 | #endif |
diff --git a/apps/plugins/puzzles/rbmalloc.c b/apps/plugins/puzzles/rbmalloc.c index 1cb903ef4f..4baca79c3d 100644 --- a/apps/plugins/puzzles/rbmalloc.c +++ b/apps/plugins/puzzles/rbmalloc.c | |||
@@ -51,7 +51,7 @@ static bool grab_audiobuf(void) | |||
51 | void *smalloc(size_t size) { | 51 | void *smalloc(size_t size) { |
52 | void *p; | 52 | void *p; |
53 | p = malloc(size); | 53 | p = malloc(size); |
54 | LOGF("allocs: %d", ++allocs); | 54 | //LOGF("allocs: %d", ++allocs); |
55 | if (!p) | 55 | if (!p) |
56 | { | 56 | { |
57 | if(grab_audiobuf()) | 57 | if(grab_audiobuf()) |
@@ -67,7 +67,7 @@ void *smalloc(size_t size) { | |||
67 | void sfree(void *p) { | 67 | void sfree(void *p) { |
68 | if (p) { | 68 | if (p) { |
69 | ++frees; | 69 | ++frees; |
70 | LOGF("frees: %d, total outstanding: %d", frees, allocs - frees); | 70 | //LOGF("frees: %d, total outstanding: %d", frees, allocs - frees); |
71 | free(p); | 71 | free(p); |
72 | } | 72 | } |
73 | } | 73 | } |
@@ -80,7 +80,7 @@ void *srealloc(void *p, size_t size) { | |||
80 | if (p) { | 80 | if (p) { |
81 | q = realloc(p, size); | 81 | q = realloc(p, size); |
82 | } else { | 82 | } else { |
83 | LOGF("allocs: %d", ++allocs); | 83 | //LOGF("allocs: %d", ++allocs); |
84 | q = malloc(size); | 84 | q = malloc(size); |
85 | } | 85 | } |
86 | if (!q) | 86 | if (!q) |
diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c index 44df35027a..f77b538019 100644 --- a/apps/plugins/puzzles/rockbox.c +++ b/apps/plugins/puzzles/rockbox.c | |||
@@ -44,6 +44,8 @@ | |||
44 | 44 | ||
45 | #include "fixedpoint.h" | 45 | #include "fixedpoint.h" |
46 | 46 | ||
47 | #include "pluginbitmaps/puzzles_cursor.h" | ||
48 | |||
47 | /* how many ticks between timer callbacks */ | 49 | /* how many ticks between timer callbacks */ |
48 | #define TIMER_INTERVAL (HZ / 50) | 50 | #define TIMER_INTERVAL (HZ / 50) |
49 | 51 | ||
@@ -122,12 +124,14 @@ static int help_times = 0; | |||
122 | 124 | ||
123 | /* clipping stuff */ | 125 | /* clipping stuff */ |
124 | static struct viewport clip_rect; | 126 | static struct viewport clip_rect; |
125 | static bool clipped = false, zoom_enabled = false, view_mode = true; | 127 | static bool clipped = false, zoom_enabled = false, view_mode = true, mouse_mode = false; |
128 | |||
129 | static int mouse_x, mouse_y; | ||
126 | 130 | ||
127 | extern bool audiobuf_available; /* defined in rbmalloc.c */ | 131 | extern bool audiobuf_available; /* defined in rbmalloc.c */ |
128 | 132 | ||
129 | static fb_data *zoom_fb; /* dynamically allocated */ | 133 | static fb_data *zoom_fb; /* dynamically allocated */ |
130 | static int zoom_w, zoom_h, zoom_clipu, zoom_clipd, zoom_clipl, zoom_clipr; | 134 | static int zoom_x, zoom_y, zoom_w, zoom_h, zoom_clipu, zoom_clipd, zoom_clipl, zoom_clipr; |
131 | static int cur_font = FONT_UI; | 135 | static int cur_font = FONT_UI; |
132 | 136 | ||
133 | static bool need_draw_update = false; | 137 | static bool need_draw_update = false; |
@@ -135,7 +139,12 @@ static int ud_l = 0, ud_u = 0, ud_r = LCD_WIDTH, ud_d = LCD_HEIGHT; | |||
135 | 139 | ||
136 | static char *titlebar = NULL; | 140 | static char *titlebar = NULL; |
137 | 141 | ||
138 | static bool want_redraw = true, accept_input = true; | 142 | /* how to process the input (custom, per-game) */ |
143 | static struct { | ||
144 | bool want_spacebar, falling_edge, ignore_repeats, rclick_on_hold; | ||
145 | } input_settings; | ||
146 | |||
147 | static bool accept_input = true; | ||
139 | 148 | ||
140 | /* last timer call */ | 149 | /* last timer call */ |
141 | static long last_tstamp; | 150 | static long last_tstamp; |
@@ -145,10 +154,10 @@ static bool load_success; | |||
145 | 154 | ||
146 | /* debug settings */ | 155 | /* debug settings */ |
147 | /* did I mention there's a secret debug menu? */ | 156 | /* did I mention there's a secret debug menu? */ |
148 | static struct settings_t { | 157 | static struct { |
149 | int slowmo_factor; | 158 | int slowmo_factor; |
150 | bool timerflash, clipoff, shortcuts, no_aa, polyanim; | 159 | bool timerflash, clipoff, shortcuts, no_aa, polyanim; |
151 | } settings; | 160 | } debug_settings; |
152 | 161 | ||
153 | /* re-implementations of many rockbox primitives, adapted to draw into | 162 | /* re-implementations of many rockbox primitives, adapted to draw into |
154 | * a custom framebuffer. */ | 163 | * a custom framebuffer. */ |
@@ -469,7 +478,7 @@ static void rb_clip(void *handle, int x, int y, int w, int h) | |||
469 | { | 478 | { |
470 | if(!zoom_enabled) | 479 | if(!zoom_enabled) |
471 | { | 480 | { |
472 | if(!settings.clipoff) | 481 | if(!debug_settings.clipoff) |
473 | { | 482 | { |
474 | LOGF("rb_clip(%d %d %d %d)", x, y, w, h); | 483 | LOGF("rb_clip(%d %d %d %d)", x, y, w, h); |
475 | clip_rect.x = MAX(0, x); | 484 | clip_rect.x = MAX(0, x); |
@@ -736,7 +745,7 @@ static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2, | |||
736 | { | 745 | { |
737 | LOGF("rb_draw_line(%d, %d, %d, %d, %d)", x1, y1, x2, y2, color); | 746 | LOGF("rb_draw_line(%d, %d, %d, %d, %d)", x1, y1, x2, y2, color); |
738 | rb_color(color); | 747 | rb_color(color); |
739 | if(settings.no_aa) | 748 | if(debug_settings.no_aa) |
740 | { | 749 | { |
741 | offset_coords(&x1, &y1); | 750 | offset_coords(&x1, &y1); |
742 | offset_coords(&x2, &y2); | 751 | offset_coords(&x2, &y2); |
@@ -968,7 +977,7 @@ static void rb_draw_poly(void *handle, int *coords, int npoints, | |||
968 | x3, y3); | 977 | x3, y3); |
969 | 978 | ||
970 | #ifdef DEBUG_MENU | 979 | #ifdef DEBUG_MENU |
971 | if(settings.polyanim) | 980 | if(debug_settings.polyanim) |
972 | { | 981 | { |
973 | rb->lcd_update(); | 982 | rb->lcd_update(); |
974 | rb->sleep(HZ/4); | 983 | rb->sleep(HZ/4); |
@@ -1014,7 +1023,7 @@ static void rb_draw_poly(void *handle, int *coords, int npoints, | |||
1014 | y1 = coords[2 * (i - 1) + 1]; | 1023 | y1 = coords[2 * (i - 1) + 1]; |
1015 | x2 = coords[2 * i]; | 1024 | x2 = coords[2 * i]; |
1016 | y2 = coords[2 * i + 1]; | 1025 | y2 = coords[2 * i + 1]; |
1017 | if(settings.no_aa) | 1026 | if(debug_settings.no_aa) |
1018 | { | 1027 | { |
1019 | offset_coords(&x1, &y1); | 1028 | offset_coords(&x1, &y1); |
1020 | offset_coords(&x2, &y2); | 1029 | offset_coords(&x2, &y2); |
@@ -1025,7 +1034,7 @@ static void rb_draw_poly(void *handle, int *coords, int npoints, | |||
1025 | draw_antialiased_line(rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); | 1034 | draw_antialiased_line(rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); |
1026 | 1035 | ||
1027 | #ifdef DEBUG_MENU | 1036 | #ifdef DEBUG_MENU |
1028 | if(settings.polyanim) | 1037 | if(debug_settings.polyanim) |
1029 | { | 1038 | { |
1030 | rb->lcd_update(); | 1039 | rb->lcd_update(); |
1031 | rb->sleep(HZ/4); | 1040 | rb->sleep(HZ/4); |
@@ -1038,7 +1047,7 @@ static void rb_draw_poly(void *handle, int *coords, int npoints, | |||
1038 | y1 = coords[1]; | 1047 | y1 = coords[1]; |
1039 | x2 = coords[2 * (npoints - 1)]; | 1048 | x2 = coords[2 * (npoints - 1)]; |
1040 | y2 = coords[2 * (npoints - 1) + 1]; | 1049 | y2 = coords[2 * (npoints - 1) + 1]; |
1041 | if(settings.no_aa) | 1050 | if(debug_settings.no_aa) |
1042 | { | 1051 | { |
1043 | offset_coords(&x1, &y1); | 1052 | offset_coords(&x1, &y1); |
1044 | offset_coords(&x2, &y2); | 1053 | offset_coords(&x2, &y2); |
@@ -1193,7 +1202,7 @@ static void rb_blitter_save(void *handle, blitter *bl, int x, int y) | |||
1193 | #if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE) | 1202 | #if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE) |
1194 | #error no vertical stride | 1203 | #error no vertical stride |
1195 | #else | 1204 | #else |
1196 | if(bl->bmp.data) | 1205 | if(bl && bl->bmp.data) |
1197 | { | 1206 | { |
1198 | int w = bl->bmp.width, h = bl->bmp.height; | 1207 | int w = bl->bmp.width, h = bl->bmp.height; |
1199 | int screen_w = zoom_enabled ? zoom_w : LCD_WIDTH; | 1208 | int screen_w = zoom_enabled ? zoom_w : LCD_WIDTH; |
@@ -1282,6 +1291,8 @@ static void rb_start_draw(void *handle) | |||
1282 | static void rb_end_draw(void *handle) | 1291 | static void rb_end_draw(void *handle) |
1283 | { | 1292 | { |
1284 | (void) handle; | 1293 | (void) handle; |
1294 | /* we ignore the backend's redraw requests and just unconditionally update everything */ | ||
1295 | #if 0 | ||
1285 | if(!zoom_enabled) | 1296 | if(!zoom_enabled) |
1286 | { | 1297 | { |
1287 | LOGF("rb_end_draw"); | 1298 | LOGF("rb_end_draw"); |
@@ -1293,6 +1304,7 @@ static void rb_end_draw(void *handle) | |||
1293 | { | 1304 | { |
1294 | /* stubbed */ | 1305 | /* stubbed */ |
1295 | } | 1306 | } |
1307 | #endif | ||
1296 | } | 1308 | } |
1297 | 1309 | ||
1298 | static void rb_status_bar(void *handle, const char *text) | 1310 | static void rb_status_bar(void *handle, const char *text) |
@@ -1347,6 +1359,54 @@ static void draw_title(bool clear_first) | |||
1347 | } | 1359 | } |
1348 | } | 1360 | } |
1349 | 1361 | ||
1362 | #define MOUSE_W BMPWIDTH_puzzles_cursor | ||
1363 | #define MOUSE_H BMPHEIGHT_puzzles_cursor | ||
1364 | |||
1365 | static blitter *mouse_bl = NULL; | ||
1366 | |||
1367 | static void clear_mouse(void) | ||
1368 | { | ||
1369 | bool orig_clipped = clipped; | ||
1370 | if(!zoom_enabled) | ||
1371 | { | ||
1372 | if(orig_clipped) | ||
1373 | rb_unclip(NULL); | ||
1374 | } | ||
1375 | |||
1376 | if(mouse_bl) | ||
1377 | rb_blitter_load(NULL, mouse_bl, BLITTER_FROMSAVED, BLITTER_FROMSAVED); | ||
1378 | |||
1379 | if(!zoom_enabled) | ||
1380 | { | ||
1381 | if(orig_clipped) | ||
1382 | rb_clip(NULL, clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height); | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1386 | static void draw_mouse(void) | ||
1387 | { | ||
1388 | bool orig_clipped = clipped; | ||
1389 | if(!zoom_enabled) | ||
1390 | { | ||
1391 | if(orig_clipped) | ||
1392 | rb_unclip(NULL); | ||
1393 | } | ||
1394 | |||
1395 | if(!mouse_bl) | ||
1396 | mouse_bl = rb_blitter_new(NULL, MOUSE_W, MOUSE_H); | ||
1397 | |||
1398 | /* save area being covered (will be restored elsewhere) */ | ||
1399 | rb_blitter_save(NULL, mouse_bl, mouse_x, mouse_y); | ||
1400 | |||
1401 | rb->lcd_bitmap_transparent(puzzles_cursor, mouse_x, mouse_y, BMPWIDTH_puzzles_cursor, BMPHEIGHT_puzzles_cursor); | ||
1402 | |||
1403 | if(!zoom_enabled) | ||
1404 | { | ||
1405 | if(orig_clipped) | ||
1406 | rb_clip(NULL, clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height); | ||
1407 | } | ||
1408 | } | ||
1409 | |||
1350 | static char *rb_text_fallback(void *handle, const char *const *strings, | 1410 | static char *rb_text_fallback(void *handle, const char *const *strings, |
1351 | int nstrings) | 1411 | int nstrings) |
1352 | { | 1412 | { |
@@ -1403,7 +1463,7 @@ void get_random_seed(void **randseed, int *randseedsize) | |||
1403 | static void timer_cb(void) | 1463 | static void timer_cb(void) |
1404 | { | 1464 | { |
1405 | #if LCD_DEPTH != 24 | 1465 | #if LCD_DEPTH != 24 |
1406 | if(settings.timerflash) | 1466 | if(debug_settings.timerflash) |
1407 | { | 1467 | { |
1408 | static bool what = false; | 1468 | static bool what = false; |
1409 | what = !what; | 1469 | what = !what; |
@@ -1416,7 +1476,7 @@ static void timer_cb(void) | |||
1416 | #endif | 1476 | #endif |
1417 | 1477 | ||
1418 | LOGF("timer callback"); | 1478 | LOGF("timer callback"); |
1419 | midend_timer(me, ((float)(*rb->current_tick - last_tstamp) / (float)HZ) / settings.slowmo_factor); | 1479 | midend_timer(me, ((float)(*rb->current_tick - last_tstamp) / (float)HZ) / debug_settings.slowmo_factor); |
1420 | last_tstamp = *rb->current_tick; | 1480 | last_tstamp = *rb->current_tick; |
1421 | } | 1481 | } |
1422 | 1482 | ||
@@ -1440,12 +1500,27 @@ void frontend_default_color(frontend *fe, float *out) | |||
1440 | 1500 | ||
1441 | /** frontend code -- mostly UI stuff **/ | 1501 | /** frontend code -- mostly UI stuff **/ |
1442 | 1502 | ||
1443 | /* set do_pausemenu to false to just return -1 on BTN_PAUSE and do | 1503 | static void send_click(int button, bool release) |
1444 | * nothing else. */ | 1504 | { |
1505 | int x = (zoom_enabled ? zoom_x : 0) + mouse_x, | ||
1506 | y = (zoom_enabled ? zoom_y : 0) + mouse_y; | ||
1507 | assert(LEFT_BUTTON + 6 == LEFT_RELEASE); | ||
1508 | |||
1509 | midend_process_key(me, x, y, button); | ||
1510 | |||
1511 | if(release) | ||
1512 | midend_process_key(me, x, y, button + 6); | ||
1513 | } | ||
1514 | |||
1515 | /* This function handles most user input. It has specific workarounds | ||
1516 | * and fixes for certain games to allow them to work well on | ||
1517 | * Rockbox. It will either return a positive value that can be passed | ||
1518 | * to the midend, or a negative flag value. Set do_pausemenu to false | ||
1519 | * to just return -1 on BTN_PAUSE and do nothing else. */ | ||
1445 | static int process_input(int tmo, bool do_pausemenu) | 1520 | static int process_input(int tmo, bool do_pausemenu) |
1446 | { | 1521 | { |
1447 | LOGF("process_input start"); | 1522 | LOGF("process_input start"); |
1448 | LOGF("------------------"); | 1523 | LOGF("-------------------"); |
1449 | int state = 0; | 1524 | int state = 0; |
1450 | 1525 | ||
1451 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 1526 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
@@ -1457,13 +1532,24 @@ static int process_input(int tmo, bool do_pausemenu) | |||
1457 | /* weird stuff */ | 1532 | /* weird stuff */ |
1458 | exit_on_usb(button); | 1533 | exit_on_usb(button); |
1459 | 1534 | ||
1460 | /* these games require a second input on long-press */ | 1535 | /* See if the button is a long-press. */ |
1461 | if(accept_input && (button == (BTN_FIRE | BUTTON_REPEAT)) && | 1536 | if(accept_input && (button == (BTN_FIRE | BUTTON_REPEAT))) |
1462 | (strcmp("Mines", midend_which_game(me)->name) != 0 || | ||
1463 | strcmp("Magnets", midend_which_game(me)->name) != 0)) | ||
1464 | { | 1537 | { |
1538 | LOGF("button is long-press, ignoring subsequent input until release"); | ||
1539 | /* Ignore repeated long presses. */ | ||
1465 | accept_input = false; | 1540 | accept_input = false; |
1466 | return ' '; | 1541 | |
1542 | if(mouse_mode && input_settings.rclick_on_hold) | ||
1543 | { | ||
1544 | /* simulate right-click */ | ||
1545 | LOGF("sending right click"); | ||
1546 | send_click(RIGHT_BUTTON, true); | ||
1547 | return 0; | ||
1548 | } | ||
1549 | |||
1550 | /* These games want a spacebar in this event. */ | ||
1551 | if(!mouse_mode && input_settings.want_spacebar) | ||
1552 | return ' '; | ||
1467 | } | 1553 | } |
1468 | 1554 | ||
1469 | button = rb->button_status(); | 1555 | button = rb->button_status(); |
@@ -1476,7 +1562,6 @@ static int process_input(int tmo, bool do_pausemenu) | |||
1476 | { | 1562 | { |
1477 | if(do_pausemenu) | 1563 | if(do_pausemenu) |
1478 | { | 1564 | { |
1479 | want_redraw = false; | ||
1480 | /* quick hack to preserve the clipping state */ | 1565 | /* quick hack to preserve the clipping state */ |
1481 | bool orig_clipped = clipped; | 1566 | bool orig_clipped = clipped; |
1482 | if(orig_clipped) | 1567 | if(orig_clipped) |
@@ -1496,13 +1581,99 @@ static int process_input(int tmo, bool do_pausemenu) | |||
1496 | return -1; | 1581 | return -1; |
1497 | } | 1582 | } |
1498 | 1583 | ||
1499 | /* these games require, for one reason or another, that events | 1584 | /* Mouse movement (if enabled). This goes here since none of the |
1585 | * following code is needed for mouse mode. */ | ||
1586 | if(mouse_mode) | ||
1587 | { | ||
1588 | if(button & BTN_UP) | ||
1589 | state = CURSOR_UP; | ||
1590 | else if(button & BTN_DOWN) | ||
1591 | state = CURSOR_DOWN; | ||
1592 | else if(button & BTN_LEFT) | ||
1593 | state = CURSOR_LEFT; | ||
1594 | else if(button & BTN_RIGHT) | ||
1595 | state = CURSOR_RIGHT; | ||
1596 | |||
1597 | unsigned released = ~button & last_keystate, | ||
1598 | pressed = button & ~last_keystate; | ||
1599 | |||
1600 | last_keystate = button; | ||
1601 | |||
1602 | /* rclick on hold requires that we fire left-click on a | ||
1603 | * release, otherwise it's impossible to distinguish the | ||
1604 | * two. */ | ||
1605 | if(input_settings.rclick_on_hold) | ||
1606 | { | ||
1607 | if(accept_input && released == BTN_FIRE) | ||
1608 | { | ||
1609 | LOGF("sending left click"); | ||
1610 | send_click(LEFT_BUTTON, true); /* right-click is handled earlier */ | ||
1611 | } | ||
1612 | } | ||
1613 | else | ||
1614 | { | ||
1615 | if(pressed & BTN_FIRE) | ||
1616 | send_click(LEFT_BUTTON, false); | ||
1617 | else if(released & BTN_FIRE) | ||
1618 | send_click(LEFT_RELEASE, false); | ||
1619 | else if(button & BTN_FIRE) | ||
1620 | send_click(LEFT_DRAG, false); | ||
1621 | } | ||
1622 | |||
1623 | static int last_mousedir = 0, held_count = 0, v = 0; | ||
1624 | |||
1625 | /* acceleration */ | ||
1626 | if(state && state == last_mousedir) | ||
1627 | { | ||
1628 | if(++held_count % 5 == 0 && v < 15) | ||
1629 | v++; | ||
1630 | } | ||
1631 | else | ||
1632 | { | ||
1633 | if(!button) | ||
1634 | { | ||
1635 | LOGF("all keys released, accepting further input"); | ||
1636 | accept_input = true; | ||
1637 | } | ||
1638 | last_mousedir = state; | ||
1639 | v = 1; | ||
1640 | held_count = 0; | ||
1641 | } | ||
1642 | |||
1643 | /* get the direction vector the cursor is moving in. */ | ||
1644 | int new_x = mouse_x, new_y = mouse_y; | ||
1645 | |||
1646 | /* in src/misc.c */ | ||
1647 | move_cursor(state, &new_x, &new_y, LCD_WIDTH, LCD_HEIGHT, FALSE); | ||
1648 | |||
1649 | int dx = new_x - mouse_x, dy = new_y - mouse_y; | ||
1650 | |||
1651 | mouse_x += dx * v; | ||
1652 | mouse_y += dy * v; | ||
1653 | |||
1654 | /* The % operator with negative operands is messy; this is much | ||
1655 | * simpler. */ | ||
1656 | if(mouse_x < 0) | ||
1657 | mouse_x = 0; | ||
1658 | if(mouse_y < 0) | ||
1659 | mouse_y = 0; | ||
1660 | |||
1661 | if(mouse_x >= LCD_WIDTH) | ||
1662 | mouse_x = LCD_WIDTH - 1; | ||
1663 | if(mouse_y >= LCD_HEIGHT) | ||
1664 | mouse_y = LCD_HEIGHT - 1; | ||
1665 | |||
1666 | /* no buttons are sent to the midend in mouse mode */ | ||
1667 | return 0; | ||
1668 | } | ||
1669 | |||
1670 | /* These games require, for one reason or another, that events | ||
1500 | * fire upon buttons being released rather than when they are | 1671 | * fire upon buttons being released rather than when they are |
1501 | * pressed */ | 1672 | * pressed. For Inertia, it is because it needs to be able to |
1502 | if(strcmp("Inertia", midend_which_game(me)->name) == 0 || | 1673 | * sense multiple simultaneous keypresses (to move diagonally), |
1503 | strcmp("Mines", midend_which_game(me)->name) == 0 || | 1674 | * and the others require a long press to map to a secondary |
1504 | strcmp("Magnets", midend_which_game(me)->name) == 0 || | 1675 | * "action" key. */ |
1505 | strcmp("Map", midend_which_game(me)->name) == 0) | 1676 | if(input_settings.falling_edge) |
1506 | { | 1677 | { |
1507 | LOGF("received button 0x%08x", button); | 1678 | LOGF("received button 0x%08x", button); |
1508 | 1679 | ||
@@ -1536,8 +1707,8 @@ static int process_input(int tmo, bool do_pausemenu) | |||
1536 | button |= released; | 1707 | button |= released; |
1537 | LOGF("accepting event 0x%08x", button); | 1708 | LOGF("accepting event 0x%08x", button); |
1538 | } | 1709 | } |
1539 | /* default is to ignore repeats except for untangle */ | 1710 | /* Ignore repeats in all games which are not Untangle. */ |
1540 | else if(strcmp("Untangle", midend_which_game(me)->name) != 0) | 1711 | else if(input_settings.ignore_repeats) |
1541 | { | 1712 | { |
1542 | /* start accepting input again after a release */ | 1713 | /* start accepting input again after a release */ |
1543 | if(!button) | 1714 | if(!button) |
@@ -1545,10 +1716,11 @@ static int process_input(int tmo, bool do_pausemenu) | |||
1545 | accept_input = true; | 1716 | accept_input = true; |
1546 | return 0; | 1717 | return 0; |
1547 | } | 1718 | } |
1548 | /* ignore repeats */ | 1719 | |
1549 | /* Untangle gets special treatment */ | 1720 | /* ignore repeats (in mouse mode, only ignore repeats of BTN_FIRE) */ |
1550 | if(!accept_input) | 1721 | if(!accept_input) |
1551 | return 0; | 1722 | return 0; |
1723 | |||
1552 | accept_input = false; | 1724 | accept_input = false; |
1553 | } | 1725 | } |
1554 | 1726 | ||
@@ -1604,7 +1776,7 @@ static int process_input(int tmo, bool do_pausemenu) | |||
1604 | break; | 1776 | break; |
1605 | } | 1777 | } |
1606 | 1778 | ||
1607 | if(settings.shortcuts) | 1779 | if(debug_settings.shortcuts) |
1608 | { | 1780 | { |
1609 | static bool shortcuts_ok = true; | 1781 | static bool shortcuts_ok = true; |
1610 | switch(button) | 1782 | switch(button) |
@@ -1665,9 +1837,9 @@ static void zoom(void) | |||
1665 | /* draws go to the zoom framebuffer */ | 1837 | /* draws go to the zoom framebuffer */ |
1666 | midend_force_redraw(me); | 1838 | midend_force_redraw(me); |
1667 | 1839 | ||
1668 | int x = 0, y = 0; | 1840 | zoom_x = zoom_y = 0; |
1669 | 1841 | ||
1670 | rb->lcd_bitmap_part(zoom_fb, x, y, STRIDE(SCREEN_MAIN, zoom_w, zoom_h), | 1842 | rb->lcd_bitmap_part(zoom_fb, zoom_x, zoom_y, STRIDE(SCREEN_MAIN, zoom_w, zoom_h), |
1671 | 0, 0, LCD_WIDTH, LCD_HEIGHT); | 1843 | 0, 0, LCD_WIDTH, LCD_HEIGHT); |
1672 | 1844 | ||
1673 | draw_title(false); /* false since we don't want to use more screen space than we need. */ | 1845 | draw_title(false); /* false since we don't want to use more screen space than we need. */ |
@@ -1693,16 +1865,16 @@ static void zoom(void) | |||
1693 | switch(button) | 1865 | switch(button) |
1694 | { | 1866 | { |
1695 | case BTN_UP: | 1867 | case BTN_UP: |
1696 | y -= PAN_Y; /* clamped later */ | 1868 | zoom_y -= PAN_Y; /* clamped later */ |
1697 | break; | 1869 | break; |
1698 | case BTN_DOWN: | 1870 | case BTN_DOWN: |
1699 | y += PAN_Y; /* clamped later */ | 1871 | zoom_y += PAN_Y; /* clamped later */ |
1700 | break; | 1872 | break; |
1701 | case BTN_LEFT: | 1873 | case BTN_LEFT: |
1702 | x -= PAN_X; /* clamped later */ | 1874 | zoom_x -= PAN_X; /* clamped later */ |
1703 | break; | 1875 | break; |
1704 | case BTN_RIGHT: | 1876 | case BTN_RIGHT: |
1705 | x += PAN_X; /* clamped later */ | 1877 | zoom_x += PAN_X; /* clamped later */ |
1706 | break; | 1878 | break; |
1707 | case BTN_PAUSE: | 1879 | case BTN_PAUSE: |
1708 | zoom_enabled = false; | 1880 | zoom_enabled = false; |
@@ -1716,15 +1888,15 @@ static void zoom(void) | |||
1716 | break; | 1888 | break; |
1717 | } | 1889 | } |
1718 | 1890 | ||
1719 | if(y < 0) | 1891 | if(zoom_y < 0) |
1720 | y = 0; | 1892 | zoom_y = 0; |
1721 | if(x < 0) | 1893 | if(zoom_x < 0) |
1722 | x = 0; | 1894 | zoom_x = 0; |
1723 | 1895 | ||
1724 | if(y + LCD_HEIGHT >= zoom_h) | 1896 | if(zoom_y + LCD_HEIGHT >= zoom_h) |
1725 | y = zoom_h - LCD_HEIGHT; | 1897 | zoom_y = zoom_h - LCD_HEIGHT; |
1726 | if(x + LCD_WIDTH >= zoom_w) | 1898 | if(zoom_x + LCD_WIDTH >= zoom_w) |
1727 | x = zoom_w - LCD_WIDTH; | 1899 | zoom_x = zoom_w - LCD_WIDTH; |
1728 | 1900 | ||
1729 | if(timer_on) | 1901 | if(timer_on) |
1730 | timer_cb(); | 1902 | timer_cb(); |
@@ -1732,7 +1904,7 @@ static void zoom(void) | |||
1732 | /* goes to zoom_fb */ | 1904 | /* goes to zoom_fb */ |
1733 | midend_redraw(me); | 1905 | midend_redraw(me); |
1734 | 1906 | ||
1735 | rb->lcd_bitmap_part(zoom_fb, x, y, STRIDE(SCREEN_MAIN, zoom_w, zoom_h), | 1907 | rb->lcd_bitmap_part(zoom_fb, zoom_x, zoom_y, STRIDE(SCREEN_MAIN, zoom_w, zoom_h), |
1736 | 0, 0, LCD_WIDTH, LCD_HEIGHT); | 1908 | 0, 0, LCD_WIDTH, LCD_HEIGHT); |
1737 | draw_title(false); | 1909 | draw_title(false); |
1738 | rb->lcd_update(); | 1910 | rb->lcd_update(); |
@@ -1755,13 +1927,26 @@ static void zoom(void) | |||
1755 | if(timer_on) | 1927 | if(timer_on) |
1756 | timer_cb(); | 1928 | timer_cb(); |
1757 | 1929 | ||
1758 | if(want_redraw) | 1930 | midend_redraw(me); |
1759 | midend_redraw(me); | ||
1760 | 1931 | ||
1761 | rb->lcd_bitmap_part(zoom_fb, x, y, STRIDE(SCREEN_MAIN, zoom_w, zoom_h), | 1932 | /* blit */ |
1933 | rb->lcd_bitmap_part(zoom_fb, zoom_x, zoom_y, STRIDE(SCREEN_MAIN, zoom_w, zoom_h), | ||
1762 | 0, 0, LCD_WIDTH, LCD_HEIGHT); | 1934 | 0, 0, LCD_WIDTH, LCD_HEIGHT); |
1935 | |||
1763 | draw_title(false); | 1936 | draw_title(false); |
1937 | |||
1938 | /* The cursor is always in screenspace coordinates; when | ||
1939 | * zoomed, this means the mouse is always restricted to | ||
1940 | * the bounds of the physical display, not the virtual | ||
1941 | * zoom framebuffer. */ | ||
1942 | if(mouse_mode) | ||
1943 | draw_mouse(); | ||
1944 | |||
1764 | rb->lcd_update(); | 1945 | rb->lcd_update(); |
1946 | |||
1947 | if(mouse_mode) | ||
1948 | clear_mouse(); | ||
1949 | |||
1765 | rb->yield(); | 1950 | rb->yield(); |
1766 | } | 1951 | } |
1767 | } | 1952 | } |
@@ -2202,12 +2387,12 @@ static void full_help(const char *name) | |||
2202 | 2387 | ||
2203 | static void init_default_settings(void) | 2388 | static void init_default_settings(void) |
2204 | { | 2389 | { |
2205 | settings.slowmo_factor = 1; | 2390 | debug_settings.slowmo_factor = 1; |
2206 | settings.timerflash = false; | 2391 | debug_settings.timerflash = false; |
2207 | settings.clipoff = false; | 2392 | debug_settings.clipoff = false; |
2208 | settings.shortcuts = false; | 2393 | debug_settings.shortcuts = false; |
2209 | settings.no_aa = false; | 2394 | debug_settings.no_aa = false; |
2210 | settings.polyanim = false; | 2395 | debug_settings.polyanim = false; |
2211 | } | 2396 | } |
2212 | 2397 | ||
2213 | #ifdef DEBUG_MENU | 2398 | #ifdef DEBUG_MENU |
@@ -2250,6 +2435,11 @@ static void debug_menu(void) | |||
2250 | "Toggle antialias", | 2435 | "Toggle antialias", |
2251 | "Benchmark antialias", | 2436 | "Benchmark antialias", |
2252 | "Toggle show poly steps", | 2437 | "Toggle show poly steps", |
2438 | "Toggle mouse mode", | ||
2439 | "Toggle spacebar on long click", | ||
2440 | "Toggle send keys on release", | ||
2441 | "Toggle ignore repeats", | ||
2442 | "Toggle right-click on hold vs. dragging", | ||
2253 | "Back"); | 2443 | "Back"); |
2254 | bool quit = false; | 2444 | bool quit = false; |
2255 | int sel = 0; | 2445 | int sel = 0; |
@@ -2258,7 +2448,7 @@ static void debug_menu(void) | |||
2258 | switch(rb->do_menu(&menu, &sel, NULL, false)) | 2448 | switch(rb->do_menu(&menu, &sel, NULL, false)) |
2259 | { | 2449 | { |
2260 | case 0: | 2450 | case 0: |
2261 | rb->set_int("Slowmo factor", "", UNIT_INT, &settings.slowmo_factor, NULL, 1, 1, 15, NULL); | 2451 | rb->set_int("Slowmo factor", "", UNIT_INT, &debug_settings.slowmo_factor, NULL, 1, 1, 15, NULL); |
2262 | break; | 2452 | break; |
2263 | case 1: | 2453 | case 1: |
2264 | { | 2454 | { |
@@ -2271,24 +2461,38 @@ static void debug_menu(void) | |||
2271 | break; | 2461 | break; |
2272 | } | 2462 | } |
2273 | case 2: | 2463 | case 2: |
2274 | settings.timerflash = !settings.timerflash; | 2464 | debug_settings.timerflash = !debug_settings.timerflash; |
2275 | break; | 2465 | break; |
2276 | case 3: | 2466 | case 3: |
2277 | settings.clipoff = !settings.clipoff; | 2467 | debug_settings.clipoff = !debug_settings.clipoff; |
2278 | break; | 2468 | break; |
2279 | case 4: | 2469 | case 4: |
2280 | settings.shortcuts = !settings.shortcuts; | 2470 | debug_settings.shortcuts = !debug_settings.shortcuts; |
2281 | break; | 2471 | break; |
2282 | case 5: | 2472 | case 5: |
2283 | settings.no_aa = !settings.no_aa; | 2473 | debug_settings.no_aa = !debug_settings.no_aa; |
2284 | break; | 2474 | break; |
2285 | case 6: | 2475 | case 6: |
2286 | bench_aa(); | 2476 | bench_aa(); |
2287 | break; | 2477 | break; |
2288 | case 7: | 2478 | case 7: |
2289 | settings.polyanim = !settings.polyanim; | 2479 | debug_settings.polyanim = !debug_settings.polyanim; |
2290 | break; | 2480 | break; |
2291 | case 8: | 2481 | case 8: |
2482 | mouse_mode = !mouse_mode; | ||
2483 | break; | ||
2484 | case 9: | ||
2485 | input_settings.want_spacebar = !input_settings.want_spacebar; | ||
2486 | break; | ||
2487 | case 10: | ||
2488 | input_settings.falling_edge = !input_settings.falling_edge; | ||
2489 | break; | ||
2490 | case 11: | ||
2491 | input_settings.ignore_repeats = !input_settings.ignore_repeats; | ||
2492 | break; | ||
2493 | case 12: | ||
2494 | input_settings.rclick_on_hold = !input_settings.rclick_on_hold; | ||
2495 | break; | ||
2292 | default: | 2496 | default: |
2293 | quit = true; | 2497 | quit = true; |
2294 | break; | 2498 | break; |
@@ -2316,8 +2520,6 @@ static int pausemenu_cb(int action, const struct menu_item_ex *this_item) | |||
2316 | if(!midend_which_game(me)->can_solve) | 2520 | if(!midend_which_game(me)->can_solve) |
2317 | return ACTION_EXIT_MENUITEM; | 2521 | return ACTION_EXIT_MENUITEM; |
2318 | break; | 2522 | break; |
2319 | case 7: | ||
2320 | break; | ||
2321 | case 9: | 2523 | case 9: |
2322 | if(audiobuf_available) | 2524 | if(audiobuf_available) |
2323 | break; | 2525 | break; |
@@ -2349,10 +2551,18 @@ static int pausemenu_cb(int action, const struct menu_item_ex *this_item) | |||
2349 | static void clear_and_draw(void) | 2551 | static void clear_and_draw(void) |
2350 | { | 2552 | { |
2351 | rb->lcd_clear_display(); | 2553 | rb->lcd_clear_display(); |
2352 | rb->lcd_update(); | ||
2353 | 2554 | ||
2354 | midend_force_redraw(me); | 2555 | midend_force_redraw(me); |
2556 | |||
2355 | draw_title(true); | 2557 | draw_title(true); |
2558 | |||
2559 | if(mouse_mode) | ||
2560 | draw_mouse(); | ||
2561 | |||
2562 | rb->lcd_update(); | ||
2563 | |||
2564 | if(mouse_mode) | ||
2565 | clear_mouse(); | ||
2356 | } | 2566 | } |
2357 | 2567 | ||
2358 | static void reset_drawing(void) | 2568 | static void reset_drawing(void) |
@@ -2482,8 +2692,8 @@ static int pause_menu(void) | |||
2482 | } | 2692 | } |
2483 | rb->lcd_set_background(BG_COLOR); | 2693 | rb->lcd_set_background(BG_COLOR); |
2484 | rb->lcd_clear_display(); | 2694 | rb->lcd_clear_display(); |
2485 | rb->lcd_update(); | ||
2486 | midend_force_redraw(me); | 2695 | midend_force_redraw(me); |
2696 | rb->lcd_update(); | ||
2487 | return 0; | 2697 | return 0; |
2488 | } | 2698 | } |
2489 | 2699 | ||
@@ -2542,6 +2752,72 @@ static void init_colors(void) | |||
2542 | sfree(floatcolors); | 2752 | sfree(floatcolors); |
2543 | } | 2753 | } |
2544 | 2754 | ||
2755 | static bool string_in_list(const char *target, const char **list) | ||
2756 | { | ||
2757 | /* list is terminated with NULL */ | ||
2758 | const char *i; | ||
2759 | |||
2760 | while((i = *list++)) | ||
2761 | { | ||
2762 | if(!strcmp(target, i)) | ||
2763 | return true; | ||
2764 | } | ||
2765 | |||
2766 | return false; | ||
2767 | } | ||
2768 | |||
2769 | static void tune_input(const char *name) | ||
2770 | { | ||
2771 | /* game-specific stuff */ | ||
2772 | |||
2773 | static const char *want_spacebar[] = { | ||
2774 | "Magnets", | ||
2775 | "Mines", | ||
2776 | "Palisade", | ||
2777 | NULL | ||
2778 | }; | ||
2779 | |||
2780 | /* these get a spacebar on long click */ | ||
2781 | input_settings.want_spacebar = string_in_list(name, want_spacebar); | ||
2782 | |||
2783 | static const char *falling_edge[] = { | ||
2784 | "Inertia", | ||
2785 | "Magnets", | ||
2786 | "Map", | ||
2787 | "Mines", | ||
2788 | "Palisade", | ||
2789 | NULL | ||
2790 | }; | ||
2791 | |||
2792 | /* wait until a key is released to send an action */ | ||
2793 | input_settings.falling_edge = string_in_list(name, falling_edge); | ||
2794 | |||
2795 | /* in all games but untangle (mouse mode overrides this) */ | ||
2796 | static const char *ignore_repeats[] = { | ||
2797 | "Untangle", | ||
2798 | NULL | ||
2799 | }; | ||
2800 | |||
2801 | input_settings.ignore_repeats = !string_in_list(name, falling_edge); | ||
2802 | |||
2803 | /* set to false if you want dragging to be possible */ | ||
2804 | static const char *rclick_on_hold[] = { | ||
2805 | "Map", | ||
2806 | "Signpost", | ||
2807 | "Untangle", | ||
2808 | NULL | ||
2809 | }; | ||
2810 | |||
2811 | input_settings.rclick_on_hold = !string_in_list(name, falling_edge); | ||
2812 | |||
2813 | static const char *mouse_games[] = { | ||
2814 | "Loopy", | ||
2815 | NULL | ||
2816 | }; | ||
2817 | |||
2818 | mouse_mode = string_in_list(name, mouse_games); | ||
2819 | } | ||
2820 | |||
2545 | static const char *init_for_game(const game *gm, int load_fd, bool draw) | 2821 | static const char *init_for_game(const game *gm, int load_fd, bool draw) |
2546 | { | 2822 | { |
2547 | me = midend_new(NULL, gm, &rb_drawing, NULL); | 2823 | me = midend_new(NULL, gm, &rb_drawing, NULL); |
@@ -2555,6 +2831,11 @@ static const char *init_for_game(const game *gm, int load_fd, bool draw) | |||
2555 | return ret; | 2831 | return ret; |
2556 | } | 2832 | } |
2557 | 2833 | ||
2834 | tune_input(gm->name); | ||
2835 | |||
2836 | mouse_x = LCD_WIDTH / 2; | ||
2837 | mouse_y = LCD_HEIGHT / 2; | ||
2838 | |||
2558 | fix_size(); | 2839 | fix_size(); |
2559 | 2840 | ||
2560 | init_colors(); | 2841 | init_colors(); |
@@ -2845,12 +3126,6 @@ enum plugin_status plugin_start(const void *param) | |||
2845 | 3126 | ||
2846 | init_tlsf(); | 3127 | init_tlsf(); |
2847 | 3128 | ||
2848 | /* sanity check */ | ||
2849 | if(fabs(sqrt(3)/2 - sin(PI/3)) > .01) | ||
2850 | { | ||
2851 | return PLUGIN_ERROR; | ||
2852 | } | ||
2853 | |||
2854 | init_default_settings(); | 3129 | init_default_settings(); |
2855 | 3130 | ||
2856 | init_fonttab(); | 3131 | init_fonttab(); |
@@ -2964,12 +3239,6 @@ enum plugin_status plugin_start(const void *param) | |||
2964 | game_loop: | 3239 | game_loop: |
2965 | while(1) | 3240 | while(1) |
2966 | { | 3241 | { |
2967 | want_redraw = true; | ||
2968 | |||
2969 | int theight = get_titleheight(); | ||
2970 | draw_title(true); | ||
2971 | rb->lcd_update_rect(0, LCD_HEIGHT - theight, LCD_WIDTH, theight); | ||
2972 | |||
2973 | int button = process_input(timer_on ? TIMER_INTERVAL : -1, true); | 3242 | int button = process_input(timer_on ? TIMER_INTERVAL : -1, true); |
2974 | 3243 | ||
2975 | if(button < 0) | 3244 | if(button < 0) |
@@ -3008,16 +3277,20 @@ enum plugin_status plugin_start(const void *param) | |||
3008 | if(button) | 3277 | if(button) |
3009 | midend_process_key(me, 0, 0, button); | 3278 | midend_process_key(me, 0, 0, button); |
3010 | 3279 | ||
3280 | if(timer_on) | ||
3281 | timer_cb(); | ||
3282 | |||
3283 | midend_redraw(me); | ||
3284 | |||
3011 | draw_title(true); /* will draw to fb */ | 3285 | draw_title(true); /* will draw to fb */ |
3012 | 3286 | ||
3013 | if(want_redraw) | 3287 | if(mouse_mode) |
3014 | midend_redraw(me); | 3288 | draw_mouse(); |
3015 | 3289 | ||
3016 | /* push title to screen as well */ | 3290 | rb->lcd_update(); |
3017 | rb->lcd_update_rect(0, LCD_HEIGHT - theight, LCD_WIDTH, theight); | ||
3018 | 3291 | ||
3019 | if(timer_on) | 3292 | if(mouse_mode) |
3020 | timer_cb(); | 3293 | clear_mouse(); |
3021 | 3294 | ||
3022 | rb->yield(); | 3295 | rb->yield(); |
3023 | } | 3296 | } |
diff --git a/apps/plugins/puzzles/src/LICENCE b/apps/plugins/puzzles/src/LICENCE index 4235005ea7..ce0418e6cc 100644 --- a/apps/plugins/puzzles/src/LICENCE +++ b/apps/plugins/puzzles/src/LICENCE | |||
@@ -1,8 +1,9 @@ | |||
1 | This software is copyright (c) 2004-2014 Simon Tatham. | 1 | This software is copyright (c) 2004-2014 Simon Tatham. |
2 | 2 | ||
3 | Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas | 3 | Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas |
4 | Kölker, Dariusz Olszewski, Michael Schierl, Lambros Lambrou, Bernd | 4 | Kölker, Dariusz Olszewski, Michael Schierl, Lambros Lambrou, Bernd |
5 | Schmidt, Steffen Bauer, Lennard Sprong and Rogier Goossens. | 5 | Schmidt, Steffen Bauer, Lennard Sprong, Rogier Goossens and Michael |
6 | Quevillon. | ||
6 | 7 | ||
7 | Permission is hereby granted, free of charge, to any person | 8 | Permission is hereby granted, free of charge, to any person |
8 | obtaining a copy of this software and associated documentation files | 9 | obtaining a copy of this software and associated documentation files |
diff --git a/apps/plugins/puzzles/src/filling.c b/apps/plugins/puzzles/src/filling.c index 7e71eb25b4..231de4c079 100644 --- a/apps/plugins/puzzles/src/filling.c +++ b/apps/plugins/puzzles/src/filling.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* -*- tab-width: 8; indent-tabs-mode: t -*- | 1 | /* -*- tab-width: 8; indent-tabs-mode: t -*- |
2 | * filling.c: An implementation of the Nikoli game fillomino. | 2 | * filling.c: An implementation of the Nikoli game fillomino. |
3 | * Copyright (C) 2007 Jonas Kölker. See LICENSE for the license. | 3 | * Copyright (C) 2007 Jonas Kölker. See LICENSE for the license. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | /* TODO: | 6 | /* TODO: |
diff --git a/apps/plugins/puzzles/src/grid.c b/apps/plugins/puzzles/src/grid.c index 52648e5a92..b5e6bb0937 100644 --- a/apps/plugins/puzzles/src/grid.c +++ b/apps/plugins/puzzles/src/grid.c | |||
@@ -2060,6 +2060,102 @@ static grid *grid_new_greathexagonal(int width, int height, const char *desc) | |||
2060 | return g; | 2060 | return g; |
2061 | } | 2061 | } |
2062 | 2062 | ||
2063 | #define KAGOME_TILESIZE 18 | ||
2064 | /* Vector for side of triangle - ratio is close to sqrt(3) */ | ||
2065 | #define KAGOME_A 15 | ||
2066 | #define KAGOME_B 26 | ||
2067 | |||
2068 | static void grid_size_kagome(int width, int height, | ||
2069 | int *tilesize, int *xextent, int *yextent) | ||
2070 | { | ||
2071 | int a = KAGOME_A; | ||
2072 | int b = KAGOME_B; | ||
2073 | |||
2074 | *tilesize = KAGOME_TILESIZE; | ||
2075 | *xextent = (4*a) * (width-1) + 6*a; | ||
2076 | *yextent = (2*b) * (height-1) + 2*b; | ||
2077 | } | ||
2078 | |||
2079 | static grid *grid_new_kagome(int width, int height, const char *desc) | ||
2080 | { | ||
2081 | int x, y; | ||
2082 | int a = KAGOME_A; | ||
2083 | int b = KAGOME_B; | ||
2084 | |||
2085 | /* Upper bounds - don't have to be exact */ | ||
2086 | int max_faces = 6 * (width + 1) * (height + 1); | ||
2087 | int max_dots = 6 * width * height; | ||
2088 | |||
2089 | tree234 *points; | ||
2090 | |||
2091 | grid *g = grid_empty(); | ||
2092 | g->tilesize = KAGOME_TILESIZE; | ||
2093 | g->faces = snewn(max_faces, grid_face); | ||
2094 | g->dots = snewn(max_dots, grid_dot); | ||
2095 | |||
2096 | points = newtree234(grid_point_cmp_fn); | ||
2097 | |||
2098 | for (y = 0; y < height; y++) { | ||
2099 | for (x = 0; x < width; x++) { | ||
2100 | grid_dot *d; | ||
2101 | /* centre of hexagon */ | ||
2102 | int px = (4*a) * x; | ||
2103 | int py = (2*b) * y; | ||
2104 | if (y % 2) | ||
2105 | px += 2*a; | ||
2106 | |||
2107 | /* hexagon */ | ||
2108 | grid_face_add_new(g, 6); | ||
2109 | d = grid_get_dot(g, points, px + a, py - b); grid_face_set_dot(g, d, 0); | ||
2110 | d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 1); | ||
2111 | d = grid_get_dot(g, points, px + a, py + b); grid_face_set_dot(g, d, 2); | ||
2112 | d = grid_get_dot(g, points, px - a, py + b); grid_face_set_dot(g, d, 3); | ||
2113 | d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 4); | ||
2114 | d = grid_get_dot(g, points, px - a, py - b); grid_face_set_dot(g, d, 5); | ||
2115 | |||
2116 | /* Triangle above right */ | ||
2117 | if ((x < width - 1) || (!(y % 2) && y)) { | ||
2118 | grid_face_add_new(g, 3); | ||
2119 | d = grid_get_dot(g, points, px + 3*a, py - b); grid_face_set_dot(g, d, 0); | ||
2120 | d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 1); | ||
2121 | d = grid_get_dot(g, points, px + a, py - b); grid_face_set_dot(g, d, 2); | ||
2122 | } | ||
2123 | |||
2124 | /* Triangle below right */ | ||
2125 | if ((x < width - 1) || (!(y % 2) && (y < height - 1))) { | ||
2126 | grid_face_add_new(g, 3); | ||
2127 | d = grid_get_dot(g, points, px + 3*a, py + b); grid_face_set_dot(g, d, 0); | ||
2128 | d = grid_get_dot(g, points, px + a, py + b); grid_face_set_dot(g, d, 1); | ||
2129 | d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 2); | ||
2130 | } | ||
2131 | |||
2132 | /* Left triangles */ | ||
2133 | if (!x && (y % 2)) { | ||
2134 | /* Triangle above left */ | ||
2135 | grid_face_add_new(g, 3); | ||
2136 | d = grid_get_dot(g, points, px - a, py - b); grid_face_set_dot(g, d, 0); | ||
2137 | d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 1); | ||
2138 | d = grid_get_dot(g, points, px - 3*a, py - b); grid_face_set_dot(g, d, 2); | ||
2139 | |||
2140 | /* Triangle below left */ | ||
2141 | if (y < height - 1) { | ||
2142 | grid_face_add_new(g, 3); | ||
2143 | d = grid_get_dot(g, points, px - a, py + b); grid_face_set_dot(g, d, 0); | ||
2144 | d = grid_get_dot(g, points, px - 3*a, py + b); grid_face_set_dot(g, d, 1); | ||
2145 | d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 2); | ||
2146 | } | ||
2147 | } | ||
2148 | } | ||
2149 | } | ||
2150 | |||
2151 | freetree234(points); | ||
2152 | assert(g->num_faces <= max_faces); | ||
2153 | assert(g->num_dots <= max_dots); | ||
2154 | |||
2155 | grid_make_consistent(g); | ||
2156 | return g; | ||
2157 | } | ||
2158 | |||
2063 | #define OCTAGONAL_TILESIZE 40 | 2159 | #define OCTAGONAL_TILESIZE 40 |
2064 | /* b/a approx sqrt(2) */ | 2160 | /* b/a approx sqrt(2) */ |
2065 | #define OCTAGONAL_A 29 | 2161 | #define OCTAGONAL_A 29 |
diff --git a/apps/plugins/puzzles/src/grid.h b/apps/plugins/puzzles/src/grid.h index 19079a44b8..26d0b16633 100644 --- a/apps/plugins/puzzles/src/grid.h +++ b/apps/plugins/puzzles/src/grid.h | |||
@@ -100,6 +100,7 @@ typedef struct grid { | |||
100 | A(SNUBSQUARE,snubsquare) \ | 100 | A(SNUBSQUARE,snubsquare) \ |
101 | A(CAIRO,cairo) \ | 101 | A(CAIRO,cairo) \ |
102 | A(GREATHEXAGONAL,greathexagonal) \ | 102 | A(GREATHEXAGONAL,greathexagonal) \ |
103 | A(KAGOME,kagome) \ | ||
103 | A(OCTAGONAL,octagonal) \ | 104 | A(OCTAGONAL,octagonal) \ |
104 | A(KITE,kites) \ | 105 | A(KITE,kites) \ |
105 | A(FLORET,floret) \ | 106 | A(FLORET,floret) \ |
diff --git a/apps/plugins/puzzles/src/loopy.c b/apps/plugins/puzzles/src/loopy.c index 5f1940e945..c14412d6be 100644 --- a/apps/plugins/puzzles/src/loopy.c +++ b/apps/plugins/puzzles/src/loopy.c | |||
@@ -278,6 +278,7 @@ static void check_caches(const solver_state* sstate); | |||
278 | A("Penrose (kite/dart)",PENROSE_P2,3,3) \ | 278 | A("Penrose (kite/dart)",PENROSE_P2,3,3) \ |
279 | A("Penrose (rhombs)",PENROSE_P3,3,3) \ | 279 | A("Penrose (rhombs)",PENROSE_P3,3,3) \ |
280 | A("Great-Great-Dodecagonal",GREATGREATDODECAGONAL,2,2) \ | 280 | A("Great-Great-Dodecagonal",GREATGREATDODECAGONAL,2,2) \ |
281 | A("Kagome",KAGOME,3,3) \ | ||
281 | /* end of list */ | 282 | /* end of list */ |
282 | 283 | ||
283 | #define GRID_NAME(title,type,amin,omin) title, | 284 | #define GRID_NAME(title,type,amin,omin) title, |
@@ -544,6 +545,7 @@ static const game_params loopy_presets_more[] = { | |||
544 | #ifdef SMALL_SCREEN | 545 | #ifdef SMALL_SCREEN |
545 | { 7, 7, DIFF_HARD, LOOPY_GRID_HONEYCOMB }, | 546 | { 7, 7, DIFF_HARD, LOOPY_GRID_HONEYCOMB }, |
546 | { 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL }, | 547 | { 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL }, |
548 | { 5, 4, DIFF_HARD, LOOPY_GRID_KAGOME }, | ||
547 | { 5, 5, DIFF_HARD, LOOPY_GRID_OCTAGONAL }, | 549 | { 5, 5, DIFF_HARD, LOOPY_GRID_OCTAGONAL }, |
548 | { 3, 3, DIFF_HARD, LOOPY_GRID_FLORET }, | 550 | { 3, 3, DIFF_HARD, LOOPY_GRID_FLORET }, |
549 | { 3, 3, DIFF_HARD, LOOPY_GRID_DODECAGONAL }, | 551 | { 3, 3, DIFF_HARD, LOOPY_GRID_DODECAGONAL }, |
@@ -552,6 +554,7 @@ static const game_params loopy_presets_more[] = { | |||
552 | #else | 554 | #else |
553 | { 10, 10, DIFF_HARD, LOOPY_GRID_HONEYCOMB }, | 555 | { 10, 10, DIFF_HARD, LOOPY_GRID_HONEYCOMB }, |
554 | { 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL }, | 556 | { 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL }, |
557 | { 5, 4, DIFF_HARD, LOOPY_GRID_KAGOME }, | ||
555 | { 7, 7, DIFF_HARD, LOOPY_GRID_OCTAGONAL }, | 558 | { 7, 7, DIFF_HARD, LOOPY_GRID_OCTAGONAL }, |
556 | { 5, 5, DIFF_HARD, LOOPY_GRID_FLORET }, | 559 | { 5, 5, DIFF_HARD, LOOPY_GRID_FLORET }, |
557 | { 5, 4, DIFF_HARD, LOOPY_GRID_DODECAGONAL }, | 560 | { 5, 4, DIFF_HARD, LOOPY_GRID_DODECAGONAL }, |
diff --git a/apps/plugins/puzzles/src/palisade.c b/apps/plugins/puzzles/src/palisade.c index 5227a1d56c..e495bbed2c 100644 --- a/apps/plugins/puzzles/src/palisade.c +++ b/apps/plugins/puzzles/src/palisade.c | |||
@@ -865,14 +865,16 @@ static char *game_text_format(const game_state *state) | |||
865 | 865 | ||
866 | struct game_ui { | 866 | struct game_ui { |
867 | int x, y; | 867 | int x, y; |
868 | unsigned int show: 1; | 868 | unsigned int show: 1; |
869 | unsigned int fake_ctrl: 1; | ||
870 | unsigned int fake_shift: 1; | ||
869 | }; | 871 | }; |
870 | 872 | ||
871 | static game_ui *new_ui(const game_state *state) | 873 | static game_ui *new_ui(const game_state *state) |
872 | { | 874 | { |
873 | game_ui *ui = snew(game_ui); | 875 | game_ui *ui = snew(game_ui); |
874 | ui->x = ui->y = 0; | 876 | ui->x = ui->y = 0; |
875 | ui->show = FALSE; | 877 | ui->show = ui->fake_ctrl = ui->fake_shift = FALSE; |
876 | return ui; | 878 | return ui; |
877 | } | 879 | } |
878 | 880 | ||
@@ -916,7 +918,10 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
916 | const game_drawstate *ds, int x, int y, int button) | 918 | const game_drawstate *ds, int x, int y, int button) |
917 | { | 919 | { |
918 | int w = state->shared->params.w, h = state->shared->params.h; | 920 | int w = state->shared->params.w, h = state->shared->params.h; |
919 | int control = button & MOD_CTRL, shift = button & MOD_SHFT; | 921 | int control = (button & MOD_CTRL) | ui->fake_ctrl, shift = (button & MOD_SHFT) | ui->fake_shift; |
922 | |||
923 | /* reset */ | ||
924 | ui->fake_ctrl = ui->fake_shift = FALSE; | ||
920 | 925 | ||
921 | button &= ~MOD_MASK; | 926 | button &= ~MOD_MASK; |
922 | 927 | ||
@@ -999,6 +1004,16 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
999 | return UI_UPDATE; | 1004 | return UI_UPDATE; |
1000 | } | 1005 | } |
1001 | } | 1006 | } |
1007 | else if(IS_CURSOR_SELECT(button)) { | ||
1008 | /* CURSOR_SELECT or CURSOR_SELECT2 tells us to toggle whether | ||
1009 | * the button press should be interpreted as having CTRL or | ||
1010 | * shift pressed along with it, respectively. */ | ||
1011 | ui->show = TRUE; | ||
1012 | if(button == CURSOR_SELECT2) | ||
1013 | ui->fake_shift = !ui->fake_shift; | ||
1014 | else | ||
1015 | ui->fake_ctrl = !ui->fake_ctrl; | ||
1016 | } | ||
1002 | 1017 | ||
1003 | return NULL; | 1018 | return NULL; |
1004 | } | 1019 | } |