forked from len0rd/rockbox
puzzles: antialiased line drawing and optional "shortcuts" for undo/redo
- line drawing should eventually be moved to xlcd, but for now it's very nonportable code - fixes a minor issue with the configuration screens Change-Id: I897f01b7210cbbec32665c2bc67920c965ea0bec
This commit is contained in:
parent
79e8cd4cfe
commit
8e4429853d
3 changed files with 319 additions and 111 deletions
|
@ -43,8 +43,8 @@ ROCKS += $(PUZZLES_ROCKS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Hack to suppress all warnings:
|
# Hack to suppress all warnings:
|
||||||
PUZZLESFLAGS = $(filter-out -O%,$(PLUGINFLAGS)) -Os \
|
PUZZLESFLAGS = $(filter-out -O%,$(PLUGINFLAGS)) -O3 \
|
||||||
-Wno-unused-parameter -Wno-sign-compare -Wno-strict-aliasing -w \
|
-Wno-unused-parameter -Wno-sign-compare -Wno-strict-aliasing -w \
|
||||||
-DFOR_REAL -I$(PUZZLES_SRCDIR)
|
-DFOR_REAL -I$(PUZZLES_SRCDIR)
|
||||||
ifdef PUZZLES_COMBINED
|
ifdef PUZZLES_COMBINED
|
||||||
PUZZLESFLAGS += -DCOMBINED
|
PUZZLESFLAGS += -DCOMBINED
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "lib/playback_control.h"
|
#include "lib/playback_control.h"
|
||||||
#endif
|
#endif
|
||||||
#include "lib/xlcd.h"
|
#include "lib/xlcd.h"
|
||||||
|
#include "fixedpoint.h"
|
||||||
|
|
||||||
/* how many ticks between timer callbacks */
|
/* how many ticks between timer callbacks */
|
||||||
#define TIMER_INTERVAL (HZ / 50)
|
#define TIMER_INTERVAL (HZ / 50)
|
||||||
|
@ -75,7 +76,7 @@ extern bool audiobuf_available;
|
||||||
|
|
||||||
static struct settings_t {
|
static struct settings_t {
|
||||||
int slowmo_factor;
|
int slowmo_factor;
|
||||||
bool bulk, timerflash, clipoff;
|
bool bulk, timerflash, clipoff, shortcuts, no_aa;
|
||||||
} settings;
|
} settings;
|
||||||
|
|
||||||
/* clipping is implemented through viewports and offsetting
|
/* 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)
|
||||||
rb->lcd_fillrect(x, y, w, h);
|
rb->lcd_fillrect(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* most of our time drawing lines is spent in this function! */
|
||||||
|
static inline void plot(unsigned x, unsigned y, unsigned long a,
|
||||||
|
unsigned long r1, unsigned long g1, unsigned long b1,
|
||||||
|
unsigned cl, unsigned cr, unsigned cu, unsigned cd)
|
||||||
|
{
|
||||||
|
/* This is really quite possibly the least efficient way of doing
|
||||||
|
this. A better way would be in draw_antialiased_line(), but the
|
||||||
|
problem with that is that the algorithms I investigated at
|
||||||
|
least were incorrect at least part of the time and didn't make
|
||||||
|
drawing much faster overall. */
|
||||||
|
if(!(cl <= x && x < cr && cu <= y && y < cd))
|
||||||
|
return;
|
||||||
|
|
||||||
|
fb_data *ptr = rb->lcd_framebuffer + y * LCD_WIDTH + x;
|
||||||
|
fb_data orig = *ptr;
|
||||||
|
unsigned long r2, g2, b2;
|
||||||
|
r2 = RGB_UNPACK_RED(orig);
|
||||||
|
g2 = RGB_UNPACK_GREEN(orig);
|
||||||
|
b2 = RGB_UNPACK_BLUE(orig);
|
||||||
|
|
||||||
|
unsigned long r, g, b;
|
||||||
|
r = ((r1 * a) + (r2 * (256 - a))) >> 8;
|
||||||
|
g = ((g1 * a) + (g2 * (256 - a))) >> 8;
|
||||||
|
b = ((b1 * a) + (b2 * (256 - a))) >> 8;
|
||||||
|
|
||||||
|
*ptr = LCD_RGBPACK(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
||||||
|
/* expects UN-OFFSET coordinates, directly access framebuffer */
|
||||||
|
static void draw_antialiased_line(int x0, int y0, int x1, int y1)
|
||||||
|
{
|
||||||
|
/* fixed-point Wu's algorithm, modified for integer-only endpoints */
|
||||||
|
|
||||||
|
/* passed to plot() to avoid re-calculation */
|
||||||
|
unsigned short l = 0, r = LCD_WIDTH, u = 0, d = LCD_HEIGHT;
|
||||||
|
if(clipped)
|
||||||
|
{
|
||||||
|
l = clip_rect.x;
|
||||||
|
r = clip_rect.x + clip_rect.width;
|
||||||
|
u = clip_rect.y;
|
||||||
|
d = clip_rect.y + clip_rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool steep = ABS(y1 - y0) > ABS(x1 - x0);
|
||||||
|
int tmp;
|
||||||
|
if(steep)
|
||||||
|
{
|
||||||
|
SWAP(x0, y0, tmp);
|
||||||
|
SWAP(x1, y1, tmp);
|
||||||
|
}
|
||||||
|
if(x0 > x1)
|
||||||
|
{
|
||||||
|
SWAP(x0, x1, tmp);
|
||||||
|
SWAP(y0, y1, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dx, dy;
|
||||||
|
dx = x1 - x0;
|
||||||
|
dy = y1 - y0;
|
||||||
|
|
||||||
|
if(!(dx << FRACBITS))
|
||||||
|
return; /* bail out */
|
||||||
|
|
||||||
|
long gradient = fp_div(dy << FRACBITS, dx << FRACBITS, FRACBITS);
|
||||||
|
long intery = (y0 << FRACBITS);
|
||||||
|
|
||||||
|
unsigned color = rb->lcd_get_foreground();
|
||||||
|
unsigned long r1, g1, b1;
|
||||||
|
r1 = RGB_UNPACK_RED(color);
|
||||||
|
g1 = RGB_UNPACK_GREEN(color);
|
||||||
|
b1 = RGB_UNPACK_BLUE(color);
|
||||||
|
|
||||||
|
/* main loop */
|
||||||
|
if(steep)
|
||||||
|
{
|
||||||
|
for(int x = x0; x <= x1; ++x, intery += gradient)
|
||||||
|
{
|
||||||
|
unsigned y = intery >> FRACBITS;
|
||||||
|
unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8);
|
||||||
|
|
||||||
|
plot(y, x, (1 << 8) - alpha, r1, g1, b1, l, r, u, d);
|
||||||
|
plot(y + 1, x, alpha, r1, g1, b1, l, r, u, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int x = x0; x <= x1; ++x, intery += gradient)
|
||||||
|
{
|
||||||
|
unsigned y = intery >> FRACBITS;
|
||||||
|
unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8);
|
||||||
|
|
||||||
|
plot(x, y, (1 << 8) - alpha, r1, g1, b1, l, r, u, d);
|
||||||
|
plot(x, y + 1, alpha, r1, g1, b1, l, r, u, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
||||||
int color)
|
int color)
|
||||||
{
|
{
|
||||||
LOGF("rb_draw_line(%d, %d, %d, %d, %d)", x1, y1, x2, y2, color);
|
LOGF("rb_draw_line(%d, %d, %d, %d, %d)", x1, y1, x2, y2, color);
|
||||||
offset_coords(&x1, &y1);
|
|
||||||
offset_coords(&x2, &y2);
|
|
||||||
rb_color(color);
|
rb_color(color);
|
||||||
rb->lcd_drawline(x1, y1, x2, y2);
|
if(settings.no_aa)
|
||||||
|
{
|
||||||
|
offset_coords(&x1, &y1);
|
||||||
|
offset_coords(&x2, &y2);
|
||||||
|
rb->lcd_drawline(x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
draw_antialiased_line(x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -351,12 +467,15 @@ static void rb_draw_poly(void *handle, int *coords, int npoints,
|
||||||
y1 = coords[2 * (i - 1) + 1];
|
y1 = coords[2 * (i - 1) + 1];
|
||||||
x2 = coords[2 * i];
|
x2 = coords[2 * i];
|
||||||
y2 = coords[2 * i + 1];
|
y2 = coords[2 * i + 1];
|
||||||
offset_coords(&x1, &y1);
|
if(settings.no_aa)
|
||||||
offset_coords(&x2, &y2);
|
{
|
||||||
rb->lcd_drawline(x1, y1,
|
offset_coords(&x1, &y1);
|
||||||
x2, y2);
|
offset_coords(&x2, &y2);
|
||||||
//rb->lcd_update();
|
rb->lcd_drawline(x1, y1,
|
||||||
//rb->sleep(HZ/2);
|
x2, y2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
draw_antialiased_line(x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int x1, y1, x2, y2;
|
int x1, y1, x2, y2;
|
||||||
|
@ -364,11 +483,16 @@ static void rb_draw_poly(void *handle, int *coords, int npoints,
|
||||||
y1 = coords[1];
|
y1 = coords[1];
|
||||||
x2 = coords[2 * (npoints - 1)];
|
x2 = coords[2 * (npoints - 1)];
|
||||||
y2 = coords[2 * (npoints - 1) + 1];
|
y2 = coords[2 * (npoints - 1) + 1];
|
||||||
offset_coords(&x1, &y1);
|
if(settings.no_aa)
|
||||||
offset_coords(&x2, &y2);
|
{
|
||||||
|
offset_coords(&x1, &y1);
|
||||||
|
offset_coords(&x2, &y2);
|
||||||
|
|
||||||
rb->lcd_drawline(x1, y1,
|
rb->lcd_drawline(x1, y1,
|
||||||
x2, y2);
|
x2, y2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
draw_antialiased_line(x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_draw_circle(void *handle, int cx, int cy, int radius,
|
static void rb_draw_circle(void *handle, int cx, int cy, int radius,
|
||||||
|
@ -394,25 +518,6 @@ struct blitter {
|
||||||
struct bitmap bmp;
|
struct bitmap bmp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static blitter *rb_blitter_new(void *handle, int w, int h)
|
|
||||||
{
|
|
||||||
LOGF("rb_blitter_new");
|
|
||||||
blitter *b = snew(blitter);
|
|
||||||
b->bmp.width = w;
|
|
||||||
b->bmp.height = h;
|
|
||||||
b->bmp.data = smalloc(w * h * sizeof(fb_data));
|
|
||||||
b->have_data = false;
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rb_blitter_free(void *handle, blitter *bl)
|
|
||||||
{
|
|
||||||
LOGF("rb_blitter_free");
|
|
||||||
sfree(bl->bmp.data);
|
|
||||||
sfree(bl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* originally from emcc.c */
|
/* originally from emcc.c */
|
||||||
static void trim_rect(int *x, int *y, int *w, int *h)
|
static void trim_rect(int *x, int *y, int *w, int *h)
|
||||||
{
|
{
|
||||||
|
@ -430,10 +535,10 @@ static void trim_rect(int *x, int *y, int *w, int *h)
|
||||||
y1 = *y + *h;
|
y1 = *y + *h;
|
||||||
|
|
||||||
/* Clip each coordinate at both extremes of the canvas */
|
/* Clip each coordinate at both extremes of the canvas */
|
||||||
x0 = (x0 < 0 ? 0 : x0 > LCD_WIDTH ? LCD_WIDTH : x0);
|
x0 = (x0 < 0 ? 0 : x0 > LCD_WIDTH - 1 ? LCD_WIDTH - 1: x0);
|
||||||
x1 = (x1 < 0 ? 0 : x1 > LCD_WIDTH ? LCD_WIDTH : x1);
|
x1 = (x1 < 0 ? 0 : x1 > LCD_WIDTH - 1 ? LCD_WIDTH - 1: x1);
|
||||||
y0 = (y0 < 0 ? 0 : y0 > LCD_HEIGHT ? LCD_HEIGHT : y0);
|
y0 = (y0 < 0 ? 0 : y0 > LCD_HEIGHT - 1 ? LCD_HEIGHT - 1: y0);
|
||||||
y1 = (y1 < 0 ? 0 : y1 > LCD_HEIGHT ? LCD_HEIGHT : y1);
|
y1 = (y1 < 0 ? 0 : y1 > LCD_HEIGHT - 1 ? LCD_HEIGHT - 1: y1);
|
||||||
|
|
||||||
/* Transform back into x,y,w,h to return */
|
/* Transform back into x,y,w,h to return */
|
||||||
*x = x0;
|
*x = x0;
|
||||||
|
@ -442,6 +547,25 @@ static void trim_rect(int *x, int *y, int *w, int *h)
|
||||||
*h = y1 - y0;
|
*h = y1 - y0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static blitter *rb_blitter_new(void *handle, int w, int h)
|
||||||
|
{
|
||||||
|
LOGF("rb_blitter_new");
|
||||||
|
blitter *b = snew(blitter);
|
||||||
|
b->bmp.width = w;
|
||||||
|
b->bmp.height = h;
|
||||||
|
b->bmp.data = smalloc(w * h * sizeof(fb_data));
|
||||||
|
b->have_data = false;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rb_blitter_free(void *handle, blitter *bl)
|
||||||
|
{
|
||||||
|
LOGF("rb_blitter_free");
|
||||||
|
sfree(bl->bmp.data);
|
||||||
|
sfree(bl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* copy a section of the framebuffer */
|
/* copy a section of the framebuffer */
|
||||||
static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
|
static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
|
@ -623,8 +747,6 @@ void get_random_seed(void **randseed, int *randseedsize)
|
||||||
*randseed = snew(long);
|
*randseed = snew(long);
|
||||||
long seed = *rb->current_tick;
|
long seed = *rb->current_tick;
|
||||||
rb->memcpy(*randseed, &seed, sizeof(seed));
|
rb->memcpy(*randseed, &seed, sizeof(seed));
|
||||||
//*(long*)*randseed = 42; // debug
|
|
||||||
//rb->splash(HZ, "DEBUG SEED ON");
|
|
||||||
*randseedsize = sizeof(long);
|
*randseedsize = sizeof(long);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,8 +805,7 @@ static int list_choose(const char *list_str, const char *title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return value is only meaningful when type == C_STRING */
|
static void do_configure_item(config_item *cfg)
|
||||||
static bool do_configure_item(config_item *cfg)
|
|
||||||
{
|
{
|
||||||
switch(cfg->type)
|
switch(cfg->type)
|
||||||
{
|
{
|
||||||
|
@ -698,11 +819,11 @@ static bool do_configure_item(config_item *cfg)
|
||||||
if(rb->kbd_input(newstr, MAX_STRLEN) < 0)
|
if(rb->kbd_input(newstr, MAX_STRLEN) < 0)
|
||||||
{
|
{
|
||||||
sfree(newstr);
|
sfree(newstr);
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
sfree(cfg->sval);
|
sfree(cfg->sval);
|
||||||
cfg->sval = newstr;
|
cfg->sval = newstr;
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
case C_BOOLEAN:
|
case C_BOOLEAN:
|
||||||
{
|
{
|
||||||
|
@ -726,7 +847,6 @@ static bool do_configure_item(config_item *cfg)
|
||||||
fatal("bad type");
|
fatal("bad type");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *config_formatter(int sel, void *data, char *buf, size_t len)
|
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)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void config_menu(void)
|
static bool config_menu(void)
|
||||||
{
|
{
|
||||||
char *title;
|
char *title;
|
||||||
config_item *config = midend_get_config(me, CFG_SETTINGS, &title);
|
config_item *config = midend_get_config(me, CFG_SETTINGS, &title);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
if(!config)
|
if(!config)
|
||||||
{
|
{
|
||||||
rb->splash(HZ, "Nothing to configure.");
|
rb->splash(HZ, "Nothing to configure.");
|
||||||
|
@ -782,22 +904,16 @@ static void config_menu(void)
|
||||||
config_item old;
|
config_item old;
|
||||||
int pos = rb->gui_synclist_get_sel_pos(&list);
|
int pos = rb->gui_synclist_get_sel_pos(&list);
|
||||||
memcpy(&old, config + pos, sizeof(old));
|
memcpy(&old, config + pos, sizeof(old));
|
||||||
char *old_str;
|
do_configure_item(config + pos);
|
||||||
if(old.type == C_STRING)
|
|
||||||
old_str = dupstr(old.sval);
|
|
||||||
bool freed_str = do_configure_item(config + pos);
|
|
||||||
char *err = midend_set_config(me, CFG_SETTINGS, config);
|
char *err = midend_set_config(me, CFG_SETTINGS, config);
|
||||||
if(err)
|
if(err)
|
||||||
{
|
{
|
||||||
rb->splash(HZ, err);
|
rb->splash(HZ, err);
|
||||||
memcpy(config + pos, &old, sizeof(old));
|
memcpy(config + pos, &old, sizeof(old));
|
||||||
if(freed_str)
|
|
||||||
config[pos].sval = old_str;
|
|
||||||
}
|
}
|
||||||
else if(old.type == C_STRING)
|
else
|
||||||
{
|
{
|
||||||
/* success, and we duplicated the old string, so free it */
|
success = true;
|
||||||
sfree(old_str);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -813,6 +929,7 @@ static void config_menu(void)
|
||||||
done:
|
done:
|
||||||
sfree(title);
|
sfree(title);
|
||||||
free_cfg(config);
|
free_cfg(config);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *preset_formatter(int sel, void *data, char *buf, size_t len)
|
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)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void presets_menu(void)
|
static bool presets_menu(void)
|
||||||
{
|
{
|
||||||
if(!midend_num_presets(me))
|
if(!midend_num_presets(me))
|
||||||
{
|
{
|
||||||
rb->splash(HZ, "No presets!");
|
rb->splash(HZ, "No presets!");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* display a list */
|
/* display a list */
|
||||||
|
@ -843,9 +960,8 @@ static void presets_menu(void)
|
||||||
int current = midend_which_preset(me);
|
int current = midend_which_preset(me);
|
||||||
rb->gui_synclist_select_item(&list, current >= 0 ? current : 0);
|
rb->gui_synclist_select_item(&list, current >= 0 ? current : 0);
|
||||||
|
|
||||||
bool done = false;
|
|
||||||
rb->gui_synclist_set_title(&list, "Game Type", NOICON);
|
rb->gui_synclist_set_title(&list, "Game Type", NOICON);
|
||||||
while (!done)
|
while(1)
|
||||||
{
|
{
|
||||||
rb->gui_synclist_draw(&list);
|
rb->gui_synclist_draw(&list);
|
||||||
int button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
|
int button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
|
||||||
|
@ -860,13 +976,11 @@ static void presets_menu(void)
|
||||||
game_params *params;
|
game_params *params;
|
||||||
midend_fetch_preset(me, sel, &junk, ¶ms);
|
midend_fetch_preset(me, sel, &junk, ¶ms);
|
||||||
midend_set_params(me, params);
|
midend_set_params(me, params);
|
||||||
done = true;
|
return true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case ACTION_STD_PREV:
|
case ACTION_STD_PREV:
|
||||||
case ACTION_STD_CANCEL:
|
case ACTION_STD_CANCEL:
|
||||||
done = true;
|
return false;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -948,6 +1062,37 @@ static void init_default_settings(void)
|
||||||
settings.slowmo_factor = 1;
|
settings.slowmo_factor = 1;
|
||||||
settings.bulk = false;
|
settings.bulk = false;
|
||||||
settings.timerflash = false;
|
settings.timerflash = false;
|
||||||
|
settings.clipoff = false;
|
||||||
|
settings.shortcuts = false;
|
||||||
|
settings.no_aa = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bench_aa(void)
|
||||||
|
{
|
||||||
|
rb->sleep(0);
|
||||||
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
rb->cpu_boost(true);
|
||||||
|
#endif
|
||||||
|
int next = *rb->current_tick + HZ;
|
||||||
|
int i = 0;
|
||||||
|
while(*rb->current_tick < next)
|
||||||
|
{
|
||||||
|
draw_antialiased_line(0, 0, 20, 31);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
rb->splashf(HZ, "%d AA lines/sec", i);
|
||||||
|
next = *rb->current_tick + HZ;
|
||||||
|
int j = 0;
|
||||||
|
while(*rb->current_tick < next)
|
||||||
|
{
|
||||||
|
rb->lcd_drawline(0, 0, 20, 31);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
rb->splashf(HZ, "%d normal lines/sec", j);
|
||||||
|
rb->splashf(HZ, "Efficiency: %d%%", 100 * i / j);
|
||||||
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
rb->cpu_boost(false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_menu(void)
|
static void debug_menu(void)
|
||||||
|
@ -958,6 +1103,9 @@ static void debug_menu(void)
|
||||||
"Toggle bulk update",
|
"Toggle bulk update",
|
||||||
"Toggle flash pixel on timer",
|
"Toggle flash pixel on timer",
|
||||||
"Toggle clip",
|
"Toggle clip",
|
||||||
|
"Toggle shortcuts",
|
||||||
|
"Toggle antialias",
|
||||||
|
"Benchmark antialias",
|
||||||
"Back");
|
"Back");
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
int sel = 0;
|
int sel = 0;
|
||||||
|
@ -988,6 +1136,15 @@ static void debug_menu(void)
|
||||||
settings.clipoff = !settings.clipoff;
|
settings.clipoff = !settings.clipoff;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
|
settings.shortcuts = !settings.shortcuts;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
settings.no_aa = !settings.no_aa;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
bench_aa();
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
default:
|
default:
|
||||||
quit = true;
|
quit = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1055,6 +1212,23 @@ static int pausemenu_cb(int action, const struct menu_item_ex *this_item)
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clear_and_draw(void)
|
||||||
|
{
|
||||||
|
rb->lcd_clear_display();
|
||||||
|
rb->lcd_update();
|
||||||
|
|
||||||
|
midend_force_redraw(me);
|
||||||
|
draw_title();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_drawing(void)
|
||||||
|
{
|
||||||
|
rb->lcd_set_viewport(NULL);
|
||||||
|
rb->lcd_set_backdrop(NULL);
|
||||||
|
rb->lcd_set_foreground(LCD_BLACK);
|
||||||
|
rb->lcd_set_background(BG_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
static int pause_menu(void)
|
static int pause_menu(void)
|
||||||
{
|
{
|
||||||
#define static auto
|
#define static auto
|
||||||
|
@ -1139,19 +1313,27 @@ static int pause_menu(void)
|
||||||
playback_control(NULL);
|
playback_control(NULL);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
presets_menu();
|
if(presets_menu())
|
||||||
midend_new_game(me);
|
{
|
||||||
fix_size();
|
midend_new_game(me);
|
||||||
quit = true;
|
fix_size();
|
||||||
|
reset_drawing();
|
||||||
|
clear_and_draw();
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
debug_menu();
|
debug_menu();
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
config_menu();
|
if(config_menu())
|
||||||
midend_new_game(me);
|
{
|
||||||
fix_size();
|
midend_new_game(me);
|
||||||
quit = true;
|
fix_size();
|
||||||
|
reset_drawing();
|
||||||
|
clear_and_draw();
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef COMBINED
|
#ifdef COMBINED
|
||||||
case 12:
|
case 12:
|
||||||
|
@ -1257,8 +1439,8 @@ static int process_input(int tmo)
|
||||||
}
|
}
|
||||||
LOGF("accepting event 0x%08x", button);
|
LOGF("accepting event 0x%08x", button);
|
||||||
}
|
}
|
||||||
/* not inertia: events fire on presses */
|
/* default is to ignore repeats except for untangle */
|
||||||
else
|
else if(strcmp("Untangle", midend_which_game(me)->name))
|
||||||
{
|
{
|
||||||
/* start accepting input again after a release */
|
/* start accepting input again after a release */
|
||||||
if(!button)
|
if(!button)
|
||||||
|
@ -1267,6 +1449,7 @@ static int process_input(int tmo)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* ignore repeats */
|
/* ignore repeats */
|
||||||
|
/* Untangle gets special treatment */
|
||||||
if(!accept_input)
|
if(!accept_input)
|
||||||
return 0;
|
return 0;
|
||||||
accept_input = false;
|
accept_input = false;
|
||||||
|
@ -1316,7 +1499,34 @@ static int process_input(int tmo)
|
||||||
case BTN_FIRE:
|
case BTN_FIRE:
|
||||||
state = CURSOR_SELECT;
|
state = CURSOR_SELECT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(settings.shortcuts)
|
||||||
|
{
|
||||||
|
static bool shortcuts_ok = true;
|
||||||
|
switch(button)
|
||||||
|
{
|
||||||
|
case BTN_LEFT | BTN_FIRE:
|
||||||
|
if(shortcuts_ok)
|
||||||
|
midend_process_key(me, 0, 0, 'u');
|
||||||
|
shortcuts_ok = false;
|
||||||
|
break;
|
||||||
|
case BTN_RIGHT | BTN_FIRE:
|
||||||
|
if(shortcuts_ok)
|
||||||
|
midend_process_key(me, 0, 0, 'r');
|
||||||
|
shortcuts_ok = false;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
shortcuts_ok = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOGF("process_input done");
|
LOGF("process_input done");
|
||||||
LOGF("------------------");
|
LOGF("------------------");
|
||||||
return state;
|
return state;
|
||||||
|
@ -1403,13 +1613,23 @@ static void write_wrapper(void *ptr, void *buf, int len)
|
||||||
rb->write(fd, buf, len);
|
rb->write(fd, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_and_draw(void)
|
static void init_colors(void)
|
||||||
{
|
{
|
||||||
rb->lcd_clear_display();
|
float *floatcolors = midend_colors(me, &ncolors);
|
||||||
rb->lcd_update();
|
|
||||||
|
|
||||||
midend_force_redraw(me);
|
/* convert them to packed RGB */
|
||||||
draw_title();
|
colors = smalloc(ncolors * sizeof(unsigned));
|
||||||
|
unsigned *ptr = colors;
|
||||||
|
float *floatptr = floatcolors;
|
||||||
|
for(int i = 0; i < ncolors; ++i)
|
||||||
|
{
|
||||||
|
int r = 255 * *(floatptr++);
|
||||||
|
int g = 255 * *(floatptr++);
|
||||||
|
int b = 255 * *(floatptr++);
|
||||||
|
LOGF("color %d is %d %d %d", i, r, g, b);
|
||||||
|
*ptr++ = LCD_RGBPACK(r, g, b);
|
||||||
|
}
|
||||||
|
sfree(floatcolors);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *init_for_game(const game *gm, int load_fd, bool draw)
|
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)
|
||||||
|
|
||||||
fix_size();
|
fix_size();
|
||||||
|
|
||||||
float *floatcolors = midend_colors(me, &ncolors);
|
init_colors();
|
||||||
|
|
||||||
/* convert them to packed RGB */
|
reset_drawing();
|
||||||
colors = smalloc(ncolors * sizeof(unsigned));
|
|
||||||
unsigned *ptr = colors;
|
|
||||||
float *floatptr = floatcolors;
|
|
||||||
for(int i = 0; i < ncolors; ++i)
|
|
||||||
{
|
|
||||||
int r = 255 * *(floatptr++);
|
|
||||||
int g = 255 * *(floatptr++);
|
|
||||||
int b = 255 * *(floatptr++);
|
|
||||||
LOGF("color %d is %d %d %d", i, r, g, b);
|
|
||||||
*ptr++ = LCD_RGBPACK(r, g, b);
|
|
||||||
}
|
|
||||||
sfree(floatcolors);
|
|
||||||
|
|
||||||
rb->lcd_set_viewport(NULL);
|
|
||||||
rb->lcd_set_backdrop(NULL);
|
|
||||||
rb->lcd_set_foreground(LCD_BLACK);
|
|
||||||
rb->lcd_set_background(BG_COLOR);
|
|
||||||
|
|
||||||
if(draw)
|
if(draw)
|
||||||
{
|
{
|
||||||
|
@ -1690,22 +1893,26 @@ enum plugin_status plugin_start(const void *param)
|
||||||
playback_control(NULL);
|
playback_control(NULL);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
presets_menu();
|
if(presets_menu())
|
||||||
if(!load_success)
|
|
||||||
{
|
{
|
||||||
|
midend_new_game(me);
|
||||||
|
fix_size();
|
||||||
|
init_colors();
|
||||||
|
reset_drawing();
|
||||||
clear_and_draw();
|
clear_and_draw();
|
||||||
goto game_loop;
|
goto game_loop;
|
||||||
}
|
}
|
||||||
quit = true;
|
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
config_menu();
|
if(config_menu())
|
||||||
if(!load_success)
|
|
||||||
{
|
{
|
||||||
|
midend_new_game(me);
|
||||||
|
fix_size();
|
||||||
|
init_colors();
|
||||||
|
reset_drawing();
|
||||||
clear_and_draw();
|
clear_and_draw();
|
||||||
goto game_loop;
|
goto game_loop;
|
||||||
}
|
}
|
||||||
quit = true;
|
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
if(load_success)
|
if(load_success)
|
||||||
|
|
|
@ -1162,18 +1162,17 @@ static char *interpret_move(const game_state *state, game_ui *ui,
|
||||||
{
|
{
|
||||||
if(ui->dragpoint < 0)
|
if(ui->dragpoint < 0)
|
||||||
{
|
{
|
||||||
if(ui->cursorpoint < 0)
|
|
||||||
{
|
|
||||||
ui->cursorpoint = 0;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We're selecting a point here. */
|
/* We're selecting a point here. */
|
||||||
/* Search all the points and find the closest one (2-D) in
|
/* Search all the points and find the closest one (2-D) in
|
||||||
* the given direction. */
|
* the given direction. */
|
||||||
int i, best;
|
int i, best;
|
||||||
long bestd;
|
long bestd;
|
||||||
|
|
||||||
|
if(ui->cursorpoint < 0)
|
||||||
|
{
|
||||||
|
ui->cursorpoint = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Begin drag. We drag the vertex _nearest_ to the pointer,
|
* Begin drag. We drag the vertex _nearest_ to the pointer,
|
||||||
* just in case one is nearly on top of another and we want
|
* 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,
|
||||||
/* Figure out if this point falls into a 90 degree
|
/* Figure out if this point falls into a 90 degree
|
||||||
* range extending from the current point */
|
* range extending from the current point */
|
||||||
|
|
||||||
float angle = atan2(-dy, dx); /* adjust for raster coordinates */
|
float angle = atan2(-dy, dx); /* negate y to adjust for raster coordinates */
|
||||||
|
|
||||||
/* offset to [0..2*PI] */
|
/* offset to [0..2*PI] */
|
||||||
if(angle < 0)
|
if(angle < 0)
|
||||||
|
@ -1494,6 +1493,8 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
|
||||||
ds->bg = bg;
|
ds->bg = bg;
|
||||||
|
|
||||||
game_compute_size(&state->params, ds->tilesize, &w, &h);
|
game_compute_size(&state->params, ds->tilesize, &w, &h);
|
||||||
|
|
||||||
|
clip(dr, 0, 0, w, h);
|
||||||
draw_rect(dr, 0, 0, w, h, bg);
|
draw_rect(dr, 0, 0, w, h, bg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue