summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/puzzles/README.rockbox41
-rw-r--r--apps/plugins/puzzles/rockbox.c351
2 files changed, 229 insertions, 163 deletions
diff --git a/apps/plugins/puzzles/README.rockbox b/apps/plugins/puzzles/README.rockbox
index dc45e73ade..94dab32c93 100644
--- a/apps/plugins/puzzles/README.rockbox
+++ b/apps/plugins/puzzles/README.rockbox
@@ -1,25 +1,40 @@
+Introduction
+============
+
This is the readme for the Rockbox port of Simon Tatham's Portable
Puzzle Collection.
-Upstream version used is 7cae89fb4b22c305b3fd98b4e1be065ad527a9f7 from
-December 2016. It should be relatively trivial to update it to a newer
-version, and should probably be done periodically as changes are made.
+The upstream version used is subject to change, as it should be
+relatively trivial to update it to a newer version. Simply copying the
+upstream repo's contents into src/ and running genhelp.sh ought to do
+it (watch out for API changes, though!).
+
+Source structure
+================
+
+Most of the upstream files in src/ are essentially untouched, apart
+from some minor adjustments to make them compile and run happily on
+Rockbox. The majority of the rockbox-specific code is found in
+rockbox.c, with some minor stuff in rbwrappers.c and rbmalloc.c.
-Most of the upstream files are essentially untouched, apart from some
-minor adjustments to make it compile happily on Rockbox. Some games
-still don't work due to issues with their cursor-only control scheme
-(untangle being the big culprit here) but the ones that don't are
-commented out in SOURCES.games. I'll get around to fixing them
-eventually.
+Help feature
+============
-Building is done rather hackily, with a rule for every puzzle to be
-built... almost 40 at the time of writing. Mr. Someone ought to figure
-out how to do that with a wildcard or something.
+The Help feature is implemented by compiling each puzzle against a
+compressed version of each puzzle's section from the upstream
+documentation. These files are stored under help/, and are generated
+by genhelp.sh from the puzzles.but file in the source
+distribution. The compression is LZ4, implemented in lz4tiny.c (for
+decompression on target), and compress.c (for generation). genhelp.sh
+should be run whenever the documentation is chagned.
Kudos to Simon (duh), and Frank, for telling me about it.
Franklin Wei (__builtin)
+Changelog
+=========
+
April 2017: Changes made to move upstream sources to a separate
subdirectory, where they are completely unmodified from the
original. Updating the upstream version is now as simple as copying a
@@ -29,3 +44,5 @@ of dummy header files.
August 2017: Every game that can be played with only the cursor keys
is now functional.
+
+October 2017: Added zoom feature.
diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c
index c97959d0d1..454ccfcaea 100644
--- a/apps/plugins/puzzles/rockbox.c
+++ b/apps/plugins/puzzles/rockbox.c
@@ -21,6 +21,15 @@
/* rockbox frontend for puzzles */
+/* This file contains the majority of the rockbox-specific code for
+ * the sgt-puzzles port. It implements a set of functions for the
+ * backend to call to actually run the games, as well as rockbox UI
+ * code (menus, input, etc). For a good overview of the rest of the
+ * puzzles code, see:
+ *
+ * <https://www.chiark.greenend.org.uk/~sgtatham/puzzles/devel/>.
+ */
+
#include "plugin.h"
#include "help.h"
@@ -44,6 +53,7 @@
#define FONT_CACHING
#endif
+/* background color (mimicking from the JS frontend) */
#define BG_R .9f /* very light gray */
#define BG_G .9f
#define BG_B .9f
@@ -52,9 +62,23 @@
#define ERROR_COLOR LCD_RGBPACK(255, 0, 0)
#define MAX_FONTS (MAXUSERFONTS - 2)
-
#define FONT_TABLE PLUGIN_GAMES_DATA_DIR "/.sgt-puzzles.fnttab"
+/* font bundle size range */
+#define BUNDLE_MIN 7
+#define BUNDLE_MAX 36
+#define BUNDLE_COUNT (BUNDLE_MAX - BUNDLE_MIN + 1)
+
+/* max length of C_STRING config vals */
+#define MAX_STRLEN 128
+
+/* try to increment a numeric config value up to this much */
+#define CHOOSER_MAX_INCR 2
+
+/* max font table line */
+#define MAX_LINE 128
+
+/* Sorry. */
#define MURICA
#ifdef MURICA
@@ -64,10 +88,25 @@
#define midend_colors midend_colours
#endif
+/* zoom stuff */
+#define ZOOM_FACTOR 3
#define PAN_X (MIN(LCD_HEIGHT, LCD_WIDTH) / 4)
#define PAN_Y (MIN(LCD_HEIGHT, LCD_WIDTH) / 4)
-#define ZOOM_FACTOR 3
+/* utility macros */
+#undef ABS
+#define ABS(a) ((a)<0?-(a):(a))
+#define SWAP(a, b, t) do { t = a; a = b; b = t; } while(0);
+#define fp_fpart(f, bits) ((f) & ((1 << (bits)) - 1))
+#define fp_rfpart(f, bits) ((1 << (bits)) - fp_fpart(f, bits))
+#define FRACBITS 16
+
+static void fix_size(void);
+static int pause_menu(void);
+static inline void plot(fb_data *fb, int w, int h,
+ unsigned x, unsigned y, unsigned long a,
+ unsigned long r1, unsigned long g1, unsigned long b1,
+ unsigned cl, unsigned cr, unsigned cu, unsigned cd);
static midend *me = NULL;
static unsigned *colors = NULL;
@@ -81,29 +120,36 @@ static bool debug_mode = false;
static int help_times = 0;
#endif
-static void fix_size(void);
-static int pause_menu(void);
-
+/* clipping stuff */
static struct viewport clip_rect;
static bool clipped = false, zoom_enabled = false, view_mode = true;
-extern bool audiobuf_available;
+extern bool audiobuf_available; /* defined in rbmalloc.c */
-static fb_data *zoom_fb;
+static fb_data *zoom_fb; /* dynamically allocated */
static int zoom_w, zoom_h, zoom_clipu, zoom_clipd, zoom_clipl, zoom_clipr;
static int cur_font = FONT_UI;
+static bool need_draw_update = false;
+static int ud_l = 0, ud_u = 0, ud_r = LCD_WIDTH, ud_d = LCD_HEIGHT;
+
+static char *titlebar = NULL;
+
+static bool want_redraw = true, accept_input = true;
+
+/* last timer call */
+static long last_tstamp;
+static volatile bool timer_on = false;
+
+static bool load_success;
+
+/* debug settings */
+/* did I mention there's a secret debug menu? */
static struct settings_t {
int slowmo_factor;
bool timerflash, clipoff, shortcuts, no_aa, polyanim;
} settings;
-static inline void plot(fb_data *fb, int w, int h,
- unsigned x, unsigned y, unsigned long a,
- unsigned long r1, unsigned long g1, unsigned long b1,
- unsigned cl, unsigned cr, unsigned cu, unsigned cd);
-
-
/* re-implementations of many rockbox primitives, adapted to draw into
* a custom framebuffer. */
static void zoom_drawpixel(int x, int y)
@@ -268,78 +314,7 @@ static void zoom_alpha_bitmap(const unsigned char *bits, int x, int y, int w, in
}
}
-/* clipping is implemented through viewports and offsetting
- * coordinates */
-static void rb_clip(void *handle, int x, int y, int w, int h)
-{
- if(!zoom_enabled)
- {
- if(!settings.clipoff)
- {
- LOGF("rb_clip(%d %d %d %d)", x, y, w, h);
- clip_rect.x = MAX(0, x);
- clip_rect.y = MAX(0, y);
- clip_rect.width = MIN(LCD_WIDTH, w);
- clip_rect.height = MIN(LCD_HEIGHT, h);
- clip_rect.font = FONT_UI;
- clip_rect.drawmode = DRMODE_SOLID;
-#if LCD_DEPTH > 1
- clip_rect.fg_pattern = LCD_DEFAULT_FG;
- clip_rect.bg_pattern = LCD_DEFAULT_BG;
-#endif
- rb->lcd_set_viewport(&clip_rect);
- clipped = true;
- }
- }
- else
- {
- zoom_clipu = y;
- zoom_clipd = y + h;
- zoom_clipl = x;
- zoom_clipr = x + w;
- }
-}
-
-static void rb_unclip(void *handle)
-{
- if(!zoom_enabled)
- {
- LOGF("rb_unclip");
- rb->lcd_set_viewport(NULL);
- clipped = false;
- }
- else
- {
- zoom_clipu = 0;
- zoom_clipd = zoom_h;
- zoom_clipl = 0;
- zoom_clipr = zoom_w;
- }
-}
-
-static void offset_coords(int *x, int *y)
-{
- if(clipped)
- {
- *x -= clip_rect.x;
- *y -= clip_rect.y;
- }
-}
-
-static void rb_color(int n)
-{
- if(n < 0)
- {
- fatal("bad color %d", n);
- return;
- }
- rb->lcd_set_foreground(colors[n]);
-}
-
-/* font bundle size range */
-#define BUNDLE_MIN 7
-#define BUNDLE_MAX 36
-#define BUNDLE_COUNT (BUNDLE_MAX - BUNDLE_MIN + 1)
+/* font management */
static struct bundled_font {
int status; /* -3 = never tried loading, or unloaded, -2 = failed to load, >= -1: loaded successfully */
@@ -467,6 +442,76 @@ fallback:
return;
}
+/*** Drawing API ***/
+
+static void offset_coords(int *x, int *y)
+{
+ if(clipped)
+ {
+ *x -= clip_rect.x;
+ *y -= clip_rect.y;
+ }
+}
+
+static void rb_color(int n)
+{
+ if(n < 0)
+ {
+ fatal("bad color %d", n);
+ return;
+ }
+ rb->lcd_set_foreground(colors[n]);
+}
+
+/* clipping is implemented through viewports and offsetting
+ * coordinates */
+static void rb_clip(void *handle, int x, int y, int w, int h)
+{
+ if(!zoom_enabled)
+ {
+ if(!settings.clipoff)
+ {
+ LOGF("rb_clip(%d %d %d %d)", x, y, w, h);
+ clip_rect.x = MAX(0, x);
+ clip_rect.y = MAX(0, y);
+ clip_rect.width = MIN(LCD_WIDTH, w);
+ clip_rect.height = MIN(LCD_HEIGHT, h);
+ clip_rect.font = FONT_UI;
+ clip_rect.drawmode = DRMODE_SOLID;
+#if LCD_DEPTH > 1
+ clip_rect.fg_pattern = LCD_DEFAULT_FG;
+ clip_rect.bg_pattern = LCD_DEFAULT_BG;
+#endif
+ rb->lcd_set_viewport(&clip_rect);
+ clipped = true;
+ }
+ }
+ else
+ {
+ zoom_clipu = y;
+ zoom_clipd = y + h;
+ zoom_clipl = x;
+ zoom_clipr = x + w;
+ }
+}
+
+static void rb_unclip(void *handle)
+{
+ if(!zoom_enabled)
+ {
+ LOGF("rb_unclip");
+ rb->lcd_set_viewport(NULL);
+ clipped = false;
+ }
+ else
+ {
+ zoom_clipu = 0;
+ zoom_clipd = zoom_h;
+ zoom_clipl = 0;
+ zoom_clipr = zoom_w;
+ }
+}
+
static void rb_draw_text(void *handle, int x, int y, int fonttype,
int fontsize, int align, int color, const char *text)
{
@@ -563,13 +608,6 @@ static void rb_draw_rect(void *handle, int x, int y, int w, int h, int color)
}
}
-#define SWAP(a, b, t) do { t = a; a = b; b = t; } while(0);
-
-#define fp_fpart(f, bits) ((f) & ((1 << (bits)) - 1))
-#define fp_rfpart(f, bits) ((1 << (bits)) - fp_fpart(f, bits))
-
-#define FRACBITS 16
-
/* a goes from 0-255, with a = 255 being fully opaque and a = 0 transparent */
static inline void plot(fb_data *fb, int w, int h,
unsigned x, unsigned y, unsigned long a,
@@ -609,9 +647,6 @@ static inline void plot(fb_data *fb, int w, int h,
#endif
}
-#undef ABS
-#define ABS(a) ((a)<0?-(a):(a))
-
/* speed benchmark: 34392 lines/sec vs 112687 non-antialiased
* lines/sec at full optimization on ipod6g */
@@ -902,6 +937,7 @@ static void zoom_filltriangle(int x1, int y1,
}
}
+/* Should probably refactor this */
static void rb_draw_poly(void *handle, int *coords, int npoints,
int fillcolor, int outlinecolor)
{
@@ -1207,10 +1243,6 @@ static void rb_blitter_load(void *handle, blitter *bl, int x, int y)
}
}
-static bool need_draw_update = false;
-
-static int ud_l = 0, ud_u = 0, ud_r = LCD_WIDTH, ud_d = LCD_HEIGHT;
-
static void rb_draw_update(void *handle, int x, int y, int w, int h)
{
LOGF("rb_draw_update(%d, %d, %d, %d)", x, y, w, h);
@@ -1260,8 +1292,6 @@ static void rb_end_draw(void *handle)
}
}
-static char *titlebar = NULL;
-
static void rb_status_bar(void *handle, const char *text)
{
if(titlebar)
@@ -1342,8 +1372,70 @@ const drawing_api rb_drawing = {
NULL,
};
-static bool want_redraw = true;
-static bool accept_input = true;
+/** functions exported to puzzles code **/
+
+void fatal(const char *fmt, ...)
+{
+ va_list ap;
+
+ rb->splash(HZ, "FATAL");
+
+ va_start(ap, fmt);
+ char buf[80];
+ rb->vsnprintf(buf, 80, fmt, ap);
+ rb->splash(HZ * 2, buf);
+ va_end(ap);
+
+ exit(1);
+}
+
+void get_random_seed(void **randseed, int *randseedsize)
+{
+ *randseed = snew(long);
+ long seed = *rb->current_tick;
+ rb->memcpy(*randseed, &seed, sizeof(seed));
+ *randseedsize = sizeof(long);
+}
+
+static void timer_cb(void)
+{
+#if LCD_DEPTH != 24
+ if(settings.timerflash)
+ {
+ static bool what = false;
+ what = !what;
+ if(what)
+ rb->lcd_framebuffer[0] = LCD_BLACK;
+ else
+ rb->lcd_framebuffer[0] = LCD_WHITE;
+ rb->lcd_update();
+ }
+#endif
+
+ LOGF("timer callback");
+ midend_timer(me, ((float)(*rb->current_tick - last_tstamp) / (float)HZ) / settings.slowmo_factor);
+ last_tstamp = *rb->current_tick;
+}
+
+void activate_timer(frontend *fe)
+{
+ last_tstamp = *rb->current_tick;
+ timer_on = true;
+}
+
+void deactivate_timer(frontend *fe)
+{
+ timer_on = false;
+}
+
+void frontend_default_color(frontend *fe, float *out)
+{
+ *out++ = BG_R;
+ *out++ = BG_G;
+ *out++ = BG_B;
+}
+
+/** frontend code -- mostly UI stuff **/
/* set do_pausemenu to false to just return -1 on BTN_PAUSE and do
* nothing else. */
@@ -1537,42 +1629,7 @@ static int process_input(int tmo, bool do_pausemenu)
return state;
}
-static long last_tstamp;
-
-static void timer_cb(void)
-{
-#if LCD_DEPTH != 24
- if(settings.timerflash)
- {
- static bool what = false;
- what = !what;
- if(what)
- rb->lcd_framebuffer[0] = LCD_BLACK;
- else
- rb->lcd_framebuffer[0] = LCD_WHITE;
- rb->lcd_update();
- }
-#endif
-
- LOGF("timer callback");
- midend_timer(me, ((float)(*rb->current_tick - last_tstamp) / (float)HZ) / settings.slowmo_factor);
- last_tstamp = *rb->current_tick;
-}
-
-static volatile bool timer_on = false;
-
-void activate_timer(frontend *fe)
-{
- last_tstamp = *rb->current_tick;
- timer_on = true;
-}
-
-void deactivate_timer(frontend *fe)
-{
- timer_on = false;
-}
-
-/* render to a virtual framebuffer and let the user pan (but not make any moves) */
+/* either pan around a zoomed-in image or play zoomed-in */
static void zoom(void)
{
rb->splash(0, "Please wait...");
@@ -1773,9 +1830,6 @@ static bool is_integer(const char *str)
return true;
}
-/* max length of C_STRING config vals */
-#define MAX_STRLEN 128
-
static void int_chooser(config_item *cfgs, int idx, int val)
{
config_item *cfg = cfgs + idx;
@@ -1819,9 +1873,6 @@ static void int_chooser(config_item *cfgs, int idx, int val)
}
if(d)
{
- /* we try to increment the value up to this much (mainly
- * a workaround for Unruly): */
-#define CHOOSER_MAX_INCR 2
const char *ret;
for(int i = 0; i < CHOOSER_MAX_INCR; ++i)
@@ -2026,7 +2077,7 @@ done:
return success;
}
-const char *preset_formatter(int sel, void *data, char *buf, size_t len)
+static const char *preset_formatter(int sel, void *data, char *buf, size_t len)
{
struct preset_menu *menu = data;
rb->snprintf(buf, len, "%s", menu->entries[sel].title);
@@ -2433,7 +2484,9 @@ static int pause_menu(void)
return 0;
}
-/* points to pluginbuf */
+/* points to pluginbuf, used by rbmalloc.c */
+/* useless side note: originally giant_buffer was a statically
+ * allocated giant array (4096KB IIRC), hence its name. */
char *giant_buffer = NULL;
static size_t giant_buffer_len = 0; /* set on start */
@@ -2528,8 +2581,6 @@ static void exit_handler(void)
#endif
}
-#define MAX_LINE 128
-
#ifdef FONT_CACHING
/* try loading the fonts indicated in the on-disk font table */
static void load_fonts(void)
@@ -2742,8 +2793,6 @@ static void save_game(void)
rb->lcd_update();
}
-static bool load_success;
-
static int mainmenu_cb(int action, const struct menu_item_ex *this_item)
{
int i = (intptr_t) this_item;