summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/puzzles/rockbox.c854
1 files changed, 678 insertions, 176 deletions
diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c
index 37d15b75b5..7b838ddb79 100644
--- a/apps/plugins/puzzles/rockbox.c
+++ b/apps/plugins/puzzles/rockbox.c
@@ -64,6 +64,11 @@
64#define midend_colors midend_colours 64#define midend_colors midend_colours
65#endif 65#endif
66 66
67#define PAN_X LCD_WIDTH / 4
68#define PAN_Y LCD_WIDTH / 4 /* not a typo */
69
70#define ZOOM_FACTOR 3
71
67static midend *me = NULL; 72static midend *me = NULL;
68static unsigned *colors = NULL; 73static unsigned *colors = NULL;
69static int ncolors = 0; 74static int ncolors = 0;
@@ -79,41 +84,206 @@ static int help_times = 0;
79static void fix_size(void); 84static void fix_size(void);
80 85
81static struct viewport clip_rect; 86static struct viewport clip_rect;
82static bool clipped = false; 87static bool clipped = false, audiobuf_available, zoom_enabled = false;
83extern bool audiobuf_available; 88
89static fb_data *zoom_fb;
90static int zoom_w, zoom_h, zoom_clipu, zoom_clipd, zoom_clipl, zoom_clipr;
91static int cur_font = FONT_UI;
84 92
85static struct settings_t { 93static struct settings_t {
86 int slowmo_factor; 94 int slowmo_factor;
87 bool timerflash, clipoff, shortcuts, no_aa, polyanim; 95 bool timerflash, clipoff, shortcuts, no_aa, polyanim;
88} settings; 96} settings;
89 97
98static inline void plot(fb_data *fb, int w, int h,
99 unsigned x, unsigned y, unsigned long a,
100 unsigned long r1, unsigned long g1, unsigned long b1,
101 unsigned cl, unsigned cr, unsigned cu, unsigned cd);
102
103
104/* re-implementations of many rockbox primitives, adapted to draw into
105 * a custom framebuffer. */
106static void zoom_drawpixel(int x, int y)
107{
108 if(y < zoom_clipu || y >= zoom_clipd)
109 return;
110
111 if(x < zoom_clipl || x >= zoom_clipr)
112 return;
113
114 zoom_fb[y * zoom_w + x] = rb->lcd_get_foreground();
115}
116
117static void zoom_hline(int l, int r, int y)
118{
119 if(y < zoom_clipu || y >= zoom_clipd)
120 return;
121 if(l > r)
122 {
123 int t = l;
124 l = r;
125 r = t;
126 }
127
128 if(l < zoom_clipl)
129 l = zoom_clipl;
130 if(r >= zoom_clipr)
131 r = zoom_clipr;
132
133 fb_data pixel = rb->lcd_get_foreground();
134 fb_data *ptr = zoom_fb + y * zoom_w + l;
135 for(int i = 0; i < r - l; ++i)
136 *ptr++ = pixel;
137}
138
139static void zoom_fillcircle(int cx, int cy, int radius)
140{
141 /* copied straight from xlcd_draw.c */
142 int d = 3 - (radius * 2);
143 int x = 0;
144 int y = radius;
145 while(x <= y)
146 {
147 zoom_hline(cx - x, cx + x, cy + y);
148 zoom_hline(cx - x, cx + x, cy - y);
149 zoom_hline(cx - y, cx + y, cy + x);
150 zoom_hline(cx - y, cx + y, cy - x);
151 if(d < 0)
152 {
153 d += (x * 4) + 6;
154 }
155 else
156 {
157 d += ((x - y) * 4) + 10;
158 --y;
159 }
160 ++x;
161 }
162}
163
164static void zoom_drawcircle(int cx, int cy, int radius)
165{
166 int d = 3 - (radius * 2);
167 int x = 0;
168 int y = radius;
169 while(x <= y)
170 {
171 zoom_drawpixel(cx + x, cy + y);
172 zoom_drawpixel(cx - x, cy + y);
173 zoom_drawpixel(cx + x, cy - y);
174 zoom_drawpixel(cx - x, cy - y);
175 zoom_drawpixel(cx + y, cy + x);
176 zoom_drawpixel(cx - y, cy + x);
177 zoom_drawpixel(cx + y, cy - x);
178 zoom_drawpixel(cx - y, cy - x);
179 if(d < 0)
180 {
181 d += (x * 4) + 6;
182 }
183 else
184 {
185 d += ((x - y) * 4) + 10;
186 --y;
187 }
188 ++x;
189 }
190}
191
192/* This format is pretty crazy: each byte holds the states of 8 pixels
193 * in a column, with bit 0 being the topmost pixel. Who needs cache
194 * efficiency? */
195static void zoom_mono_bitmap(const unsigned char *bits, int x, int y, int w, int h)
196{
197 for(int i = 0; i < h / 8 + 1; ++i)
198 {
199 for(int j = 0; j < w; ++j)
200 {
201 unsigned char column = bits[i * w + j];
202 for(int dy = 0; dy < 8; ++dy)
203 {
204 if(column & 1)
205 zoom_fb[(y + i * 8 + dy) * zoom_w + x + j] = LCD_BLACK;
206 column >>= 1;
207 }
208 }
209 }
210}
211
212/* Rockbox's alpha format is actually pretty sane: each byte holds
213 * alpha values for two horizontally adjacent pixels. Low half is
214 * leftmost pixel. See lcd-16bit-common.c for more info. */
215static void zoom_alpha_bitmap(const unsigned char *bits, int x, int y, int w, int h)
216{
217 const unsigned char *ptr = bits;
218 unsigned char buf;
219 int n_read = 0; /* how many 4-bit nibbles we've read (read new when even) */
220 for(int i = 0; i < h; ++i)
221 {
222 for(int j = 0; j < w; ++j)
223 {
224 if(n_read % 2 == 0)
225 {
226 buf = *ptr++;
227 }
228 int pix_alpha = (n_read++ % 2) ? buf >> 4 : buf & 0xF; /* in reverse order */
229
230 pix_alpha = 15 - pix_alpha; /* correct order now, still 0-F */
231
232 int plot_alpha = (pix_alpha << 4) | pix_alpha; /* so 0xF -> 0xFF, 0x1 -> 0x11, etc. */
233
234 plot(zoom_fb, zoom_w, zoom_h, x + j, y + i, plot_alpha, 0, 0, 0,
235 0, zoom_w, 0, zoom_h);
236 }
237 }
238}
239
90/* clipping is implemented through viewports and offsetting 240/* clipping is implemented through viewports and offsetting
91 * coordinates */ 241 * coordinates */
92static void rb_clip(void *handle, int x, int y, int w, int h) 242static void rb_clip(void *handle, int x, int y, int w, int h)
93{ 243{
94 if(!settings.clipoff) 244 if(!zoom_enabled)
95 { 245 {
96 LOGF("rb_clip(%d %d %d %d)", x, y, w, h); 246 if(!settings.clipoff)
97 clip_rect.x = MAX(0, x); 247 {
98 clip_rect.y = MAX(0, y); 248 LOGF("rb_clip(%d %d %d %d)", x, y, w, h);
99 clip_rect.width = MIN(LCD_WIDTH, w); 249 clip_rect.x = MAX(0, x);
100 clip_rect.height = MIN(LCD_HEIGHT, h); 250 clip_rect.y = MAX(0, y);
101 clip_rect.font = FONT_UI; 251 clip_rect.width = MIN(LCD_WIDTH, w);
102 clip_rect.drawmode = DRMODE_SOLID; 252 clip_rect.height = MIN(LCD_HEIGHT, h);
253 clip_rect.font = FONT_UI;
254 clip_rect.drawmode = DRMODE_SOLID;
103#if LCD_DEPTH > 1 255#if LCD_DEPTH > 1
104 clip_rect.fg_pattern = LCD_DEFAULT_FG; 256 clip_rect.fg_pattern = LCD_DEFAULT_FG;
105 clip_rect.bg_pattern = LCD_DEFAULT_BG; 257 clip_rect.bg_pattern = LCD_DEFAULT_BG;
106#endif 258#endif
107 rb->lcd_set_viewport(&clip_rect); 259 rb->lcd_set_viewport(&clip_rect);
108 clipped = true; 260 clipped = true;
261 }
262 }
263 else
264 {
265 zoom_clipu = y;
266 zoom_clipd = y + h;
267 zoom_clipl = x;
268 zoom_clipr = x + w;
109 } 269 }
110} 270}
111 271
112static void rb_unclip(void *handle) 272static void rb_unclip(void *handle)
113{ 273{
114 LOGF("rb_unclip"); 274 if(!zoom_enabled)
115 rb->lcd_set_viewport(NULL); 275 {
116 clipped = false; 276 LOGF("rb_unclip");
277 rb->lcd_set_viewport(NULL);
278 clipped = false;
279 }
280 else
281 {
282 zoom_clipu = 0;
283 zoom_clipd = LCD_HEIGHT;
284 zoom_clipl = 0;
285 zoom_clipr = LCD_WIDTH;
286 }
117} 287}
118 288
119static void offset_coords(int *x, int *y) 289static void offset_coords(int *x, int *y)
@@ -158,7 +328,8 @@ static void unload_fonts(void)
158 loaded_fonts[i].status = -3; 328 loaded_fonts[i].status = -3;
159 } 329 }
160 access_counter = -1; 330 access_counter = -1;
161 rb->lcd_setfont(FONT_UI); 331 cur_font = FONT_UI;
332 rb->lcd_setfont(cur_font);
162} 333}
163 334
164static void init_fonttab(void) 335static void init_fonttab(void)
@@ -241,7 +412,8 @@ static void rb_setfont(int type, int size)
241 goto fallback; 412 goto fallback;
242 loaded_fonts[font_idx].last_use = access_counter++; 413 loaded_fonts[font_idx].last_use = access_counter++;
243 n_fonts++; 414 n_fonts++;
244 rb->lcd_setfont(loaded_fonts[font_idx].status); 415 cur_font = loaded_fonts[font_idx].status;
416 rb->lcd_setfont(cur_font);
245 break; 417 break;
246 } 418 }
247 case -2: 419 case -2:
@@ -249,15 +421,16 @@ static void rb_setfont(int type, int size)
249 goto fallback; 421 goto fallback;
250 default: 422 default:
251 loaded_fonts[font_idx].last_use = access_counter++; 423 loaded_fonts[font_idx].last_use = access_counter++;
252 rb->lcd_setfont(loaded_fonts[font_idx].status); 424 cur_font = loaded_fonts[font_idx].status;
425 rb->lcd_setfont(cur_font);
253 break; 426 break;
254 } 427 }
255 428
256 return; 429 return;
257 430
258fallback: 431fallback:
259 432 cur_font = type == FONT_FIXED ? FONT_SYSFIXED : FONT_UI;
260 rb->lcd_setfont(type == FONT_FIXED ? FONT_SYSFIXED : FONT_UI); 433 rb->lcd_setfont(cur_font);
261 434
262 return; 435 return;
263} 436}
@@ -266,37 +439,95 @@ static void rb_draw_text(void *handle, int x, int y, int fonttype,
266 int fontsize, int align, int color, char *text) 439 int fontsize, int align, int color, char *text)
267{ 440{
268 (void) fontsize; 441 (void) fontsize;
269 LOGF("rb_draw_text(%d %d %s)", x, y, text); 442 if(!zoom_enabled)
443 {
444 LOGF("rb_draw_text(%d %d %s)", x, y, text);
445
446 offset_coords(&x, &y);
447
448 rb_setfont(fonttype, fontsize);
449
450 int w, h;
451 rb->lcd_getstringsize(text, &w, &h);
452
453 if(align & ALIGN_VNORMAL)
454 y -= h;
455 else if(align & ALIGN_VCENTRE)
456 y -= h / 2;
457
458 if(align & ALIGN_HCENTRE)
459 x -= w / 2;
460 else if(align & ALIGN_HRIGHT)
461 x -= w;
270 462
271 offset_coords(&x, &y); 463 rb_color(color);
464 rb->lcd_set_drawmode(DRMODE_FG);
465 rb->lcd_putsxy(x, y, text);
466 rb->lcd_set_drawmode(DRMODE_SOLID);
467 }
468 else
469 {
470 rb_setfont(fonttype, fontsize); /* size will be clamped if too large */
272 471
273 rb_setfont(fonttype, fontsize); 472 int w, h;
473 rb->lcd_getstringsize(text, &w, &h);
274 474
275 int w, h; 475 if(align & ALIGN_VNORMAL)
276 rb->lcd_getstringsize(text, &w, &h); 476 y -= h;
477 else if(align & ALIGN_VCENTRE)
478 y -= h / 2;
277 479
278 if(align & ALIGN_VNORMAL) 480 if(align & ALIGN_HCENTRE)
279 y -= h; 481 x -= w / 2;
280 else if(align & ALIGN_VCENTRE) 482 else if(align & ALIGN_HRIGHT)
281 y -= h / 2; 483 x -= w;
282 484
283 if(align & ALIGN_HCENTRE) 485 /* we need to access the font bitmap directly */
284 x -= w / 2; 486 struct font *pf = rb->font_get(cur_font);
285 else if(align & ALIGN_HRIGHT)
286 x -= w;
287 487
288 rb_color(color); 488 while(*text)
289 rb->lcd_set_drawmode(DRMODE_FG); 489 {
290 rb->lcd_putsxy(x, y, text); 490 /* still only reads 1 byte */
291 rb->lcd_set_drawmode(DRMODE_SOLID); 491 unsigned short c = *text++;
492 const unsigned char *bits = rb->font_get_bits(pf, c);
493 int width = rb->font_get_width(pf, c);
494
495 /* straight from lcd-bitmap-common.c */
496#if defined(HAVE_LCD_COLOR)
497 if (pf->depth)
498 {
499 /* lcd_alpha_bitmap_part isn't exported directly. However,
500 * we can create a null bitmap struct with only an alpha
501 * channel to make lcd_bmp_part call it for us. */
502
503 zoom_alpha_bitmap(bits, x, y, width, pf->height);
504 }
505 else
506#endif
507 zoom_mono_bitmap(bits, x, y, width, pf->height);
508 x += width;
509 }
510 }
292} 511}
293 512
294static void rb_draw_rect(void *handle, int x, int y, int w, int h, int color) 513static void rb_draw_rect(void *handle, int x, int y, int w, int h, int color)
295{ 514{
296 LOGF("rb_draw_rect(%d, %d, %d, %d, %d)", x, y, w, h, color); 515 if(!zoom_enabled)
297 rb_color(color); 516 {
298 offset_coords(&x, &y); 517 LOGF("rb_draw_rect(%d, %d, %d, %d, %d)", x, y, w, h, color);
299 rb->lcd_fillrect(x, y, w, h); 518 rb_color(color);
519 offset_coords(&x, &y);
520 rb->lcd_fillrect(x, y, w, h);
521 }
522 else
523 {
524 /* TODO: clipping */
525 for(int i = y; i < y + h; ++i)
526 for(int j = x; j < x + w; ++j)
527 {
528 zoom_fb[i * zoom_w + j] = colors[color];
529 }
530 }
300} 531}
301 532
302#define SWAP(a, b, t) do { t = a; a = b; b = t; } while(0); 533#define SWAP(a, b, t) do { t = a; a = b; b = t; } while(0);
@@ -306,8 +537,9 @@ static void rb_draw_rect(void *handle, int x, int y, int w, int h, int color)
306 537
307#define FRACBITS 16 538#define FRACBITS 16
308 539
309/* most of our time drawing lines is spent in this function! */ 540/* a goes from 0-255, with a = 255 being fully opaque and a = 0 transparent */
310static inline void plot(unsigned x, unsigned y, unsigned long a, 541static inline void plot(fb_data *fb, int w, int h,
542 unsigned x, unsigned y, unsigned long a,
311 unsigned long r1, unsigned long g1, unsigned long b1, 543 unsigned long r1, unsigned long g1, unsigned long b1,
312 unsigned cl, unsigned cr, unsigned cu, unsigned cd) 544 unsigned cl, unsigned cr, unsigned cu, unsigned cd)
313{ 545{
@@ -319,7 +551,7 @@ static inline void plot(unsigned x, unsigned y, unsigned long a,
319 if(!(cl <= x && x < cr && cu <= y && y < cd)) 551 if(!(cl <= x && x < cr && cu <= y && y < cd))
320 return; 552 return;
321 553
322 fb_data *ptr = rb->lcd_framebuffer + y * LCD_WIDTH + x; 554 fb_data *ptr = fb + y * w + x;
323 fb_data orig = *ptr; 555 fb_data orig = *ptr;
324 unsigned long r2, g2, b2; 556 unsigned long r2, g2, b2;
325#if LCD_DEPTH != 24 557#if LCD_DEPTH != 24
@@ -351,18 +583,28 @@ static inline void plot(unsigned x, unsigned y, unsigned long a,
351 * lines/sec at full optimization on ipod6g */ 583 * lines/sec at full optimization on ipod6g */
352 584
353/* expects UN-OFFSET coordinates, directly access framebuffer */ 585/* expects UN-OFFSET coordinates, directly access framebuffer */
354static void draw_antialiased_line(int x0, int y0, int x1, int y1) 586static void draw_antialiased_line(fb_data *fb, int w, int h, int x0, int y0, int x1, int y1)
355{ 587{
356 /* fixed-point Wu's algorithm, modified for integer-only endpoints */ 588 /* fixed-point Wu's algorithm, modified for integer-only endpoints */
357 589
358 /* passed to plot() to avoid re-calculation */ 590 /* passed to plot() to avoid re-calculation */
359 unsigned short l = 0, r = LCD_WIDTH, u = 0, d = LCD_HEIGHT; 591 unsigned short l = 0, r = w, u = 0, d = h;
360 if(clipped) 592 if(!zoom_enabled)
361 { 593 {
362 l = clip_rect.x; 594 if(clipped)
363 r = clip_rect.x + clip_rect.width; 595 {
364 u = clip_rect.y; 596 l = clip_rect.x;
365 d = clip_rect.y + clip_rect.height; 597 r = clip_rect.x + clip_rect.width;
598 u = clip_rect.y;
599 d = clip_rect.y + clip_rect.height;
600 }
601 }
602 else
603 {
604 l = zoom_clipl;
605 r = zoom_clipr;
606 u = zoom_clipu;
607 d = zoom_clipd;
366 } 608 }
367 609
368 bool steep = ABS(y1 - y0) > ABS(x1 - x0); 610 bool steep = ABS(y1 - y0) > ABS(x1 - x0);
@@ -402,8 +644,8 @@ static void draw_antialiased_line(int x0, int y0, int x1, int y1)
402 unsigned y = intery >> FRACBITS; 644 unsigned y = intery >> FRACBITS;
403 unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8); 645 unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8);
404 646
405 plot(y, x, (1 << 8) - alpha, r1, g1, b1, l, r, u, d); 647 plot(fb, w, h, y, x, (1 << 8) - alpha, r1, g1, b1, l, r, u, d);
406 plot(y + 1, x, alpha, r1, g1, b1, l, r, u, d); 648 plot(fb, w, h, y + 1, x, alpha, r1, g1, b1, l, r, u, d);
407 } 649 }
408 } 650 }
409 else 651 else
@@ -413,8 +655,8 @@ static void draw_antialiased_line(int x0, int y0, int x1, int y1)
413 unsigned y = intery >> FRACBITS; 655 unsigned y = intery >> FRACBITS;
414 unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8); 656 unsigned alpha = fp_fpart(intery, FRACBITS) >> (FRACBITS - 8);
415 657
416 plot(x, y, (1 << 8) - alpha, r1, g1, b1, l, r, u, d); 658 plot(fb, w, h, x, y, (1 << 8) - alpha, r1, g1, b1, l, r, u, d);
417 plot(x, y + 1, alpha, r1, g1, b1, l, r, u, d); 659 plot(fb, w, h, x, y + 1, alpha, r1, g1, b1, l, r, u, d);
418 } 660 }
419 } 661 }
420} 662}
@@ -422,16 +664,27 @@ static void draw_antialiased_line(int x0, int y0, int x1, int y1)
422static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2, 664static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2,
423 int color) 665 int color)
424{ 666{
425 LOGF("rb_draw_line(%d, %d, %d, %d, %d)", x1, y1, x2, y2, color); 667 if(!zoom_enabled)
426 rb_color(color);
427 if(settings.no_aa)
428 { 668 {
429 offset_coords(&x1, &y1); 669 LOGF("rb_draw_line(%d, %d, %d, %d, %d)", x1, y1, x2, y2, color);
430 offset_coords(&x2, &y2); 670 rb_color(color);
431 rb->lcd_drawline(x1, y1, x2, y2); 671 if(settings.no_aa)
672 {
673 offset_coords(&x1, &y1);
674 offset_coords(&x2, &y2);
675 rb->lcd_drawline(x1, y1, x2, y2);
676 }
677 else
678 draw_antialiased_line(rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
432 } 679 }
433 else 680 else
434 draw_antialiased_line(x1, y1, x2, y2); 681 {
682 /* draw_antialiased_line uses rb->lcd_get_foreground() to get
683 * the color */
684 rb_color(color);
685
686 draw_antialiased_line(zoom_fb, zoom_w, zoom_h, x1, y1, x2, y2);
687 }
435} 688}
436 689
437#if 0 690#if 0
@@ -489,7 +742,7 @@ static void fill_poly_line(int scanline, int count, int *pxy)
489 intersection[num_of_intersects] = 742 intersection[num_of_intersects] =
490 x1+((scanline-y1)*(x2-x1))/(y2-y1); 743 x1+((scanline-y1)*(x2-x1))/(y2-y1);
491 if ( (direct!=old_direct) 744 if ( (direct!=old_direct)
492 || (intersection[num_of_intersects] != intersection[num_of_intersects-1]) 745 || (intersection[num_of_intersects] != intersection[num_of_intersects-1])
493 ) 746 )
494 ++num_of_intersects; 747 ++num_of_intersects;
495 } 748 }
@@ -531,32 +784,176 @@ static void v_fillarea(int count, int *pxy)
531} 784}
532#endif 785#endif
533 786
787/* I'm a horrible person: this was copy-pasta'd straight from
788 * xlcd_draw.c */
789
790/* sort the given coordinates by increasing x value */
791static void sort_points_by_increasing_x(int* x1, int* y1,
792 int* x2, int* y2,
793 int* x3, int* y3)
794{
795 int x, y;
796 if (*x1 > *x3)
797 {
798 if (*x2 < *x3) /* x2 < x3 < x1 */
799 {
800 x = *x1; *x1 = *x2; *x2 = *x3; *x3 = x;
801 y = *y1; *y1 = *y2; *y2 = *y3; *y3 = y;
802 }
803 else if (*x2 > *x1) /* x3 < x1 < x2 */
804 {
805 x = *x1; *x1 = *x3; *x3 = *x2; *x2 = x;
806 y = *y1; *y1 = *y3; *y3 = *y2; *y2 = y;
807 }
808 else /* x3 <= x2 <= x1 */
809 {
810 x = *x1; *x1 = *x3; *x3 = x;
811 y = *y1; *y1 = *y3; *y3 = y;
812 }
813 }
814 else
815 {
816 if (*x2 < *x1) /* x2 < x1 <= x3 */
817 {
818 x = *x1; *x1 = *x2; *x2 = x;
819 y = *y1; *y1 = *y2; *y2 = y;
820 }
821 else if (*x2 > *x3) /* x1 <= x3 < x2 */
822 {
823 x = *x2; *x2 = *x3; *x3 = x;
824 y = *y2; *y2 = *y3; *y3 = y;
825 }
826 /* else already sorted */
827 }
828}
829
830#define sort_points_by_increasing_y(x1, y1, x2, y2, x3, y3) \
831 sort_points_by_increasing_x(y1, x1, y2, x2, y3, x3)
832
833/* draw a filled triangle, using horizontal lines for speed */
834static void zoom_filltriangle(int x1, int y1,
835 int x2, int y2,
836 int x3, int y3)
837{
838 long fp_x1, fp_x2, fp_dx1, fp_dx2;
839 int y;
840 sort_points_by_increasing_y(&x1, &y1, &x2, &y2, &x3, &y3);
841
842 if (y1 < y3) /* draw */
843 {
844 fp_dx1 = ((x3 - x1) << 16) / (y3 - y1);
845 fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1);
846
847 if (y1 < y2) /* first part */
848 {
849 fp_dx2 = ((x2 - x1) << 16) / (y2 - y1);
850 fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1);
851 for (y = y1; y < y2; y++)
852 {
853 zoom_hline(fp_x1 >> 16, fp_x2 >> 16, y);
854 fp_x1 += fp_dx1;
855 fp_x2 += fp_dx2;
856 }
857 }
858 if (y2 < y3) /* second part */
859 {
860 fp_dx2 = ((x3 - x2) << 16) / (y3 - y2);
861 fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1);
862 for (y = y2; y < y3; y++)
863 {
864 zoom_hline(fp_x1 >> 16, fp_x2 >> 16, y);
865 fp_x1 += fp_dx1;
866 fp_x2 += fp_dx2;
867 }
868 }
869 }
870}
871
534static void rb_draw_poly(void *handle, int *coords, int npoints, 872static void rb_draw_poly(void *handle, int *coords, int npoints,
535 int fillcolor, int outlinecolor) 873 int fillcolor, int outlinecolor)
536{ 874{
537 LOGF("rb_draw_poly"); 875 if(!zoom_enabled)
538
539 if(fillcolor >= 0)
540 { 876 {
541 rb_color(fillcolor); 877 LOGF("rb_draw_poly");
878
879 if(fillcolor >= 0)
880 {
881 rb_color(fillcolor);
542#if 1 882#if 1
543 /* serious hack: draw a bunch of triangles between adjacent points */ 883 /* serious hack: draw a bunch of triangles between adjacent points */
544 /* this generally works, even with some concave polygons */ 884 /* this generally works, even with some concave polygons */
545 for(int i = 2; i < npoints; ++i) 885 for(int i = 2; i < npoints; ++i)
886 {
887 int x1, y1, x2, y2, x3, y3;
888 x1 = coords[0];
889 y1 = coords[1];
890 x2 = coords[(i - 1) * 2];
891 y2 = coords[(i - 1) * 2 + 1];
892 x3 = coords[i * 2];
893 y3 = coords[i * 2 + 1];
894 offset_coords(&x1, &y1);
895 offset_coords(&x2, &y2);
896 offset_coords(&x3, &y3);
897 xlcd_filltriangle(x1, y1,
898 x2, y2,
899 x3, y3);
900
901#ifdef DEBUG_MENU
902 if(settings.polyanim)
903 {
904 rb->lcd_update();
905 rb->sleep(HZ/4);
906 }
907#endif
908#if 0
909 /* debug code */
910 rb->lcd_set_foreground(LCD_RGBPACK(255,0,0));
911 rb->lcd_drawpixel(x1, y1);
912 rb->lcd_drawpixel(x2, y2);
913 rb->lcd_drawpixel(x3, y3);
914 rb->lcd_update();
915 rb->sleep(HZ);
916 rb_color(fillcolor);
917 rb->lcd_drawpixel(x1, y1);
918 rb->lcd_drawpixel(x2, y2);
919 rb->lcd_drawpixel(x3, y3);
920 rb->lcd_update();
921#endif
922 }
923#else
924 int *pxy = smalloc(sizeof(int) * 2 * npoints + 2);
925 /* copy points, offsetted */
926 for(int i = 0; i < npoints; ++i)
927 {
928 pxy[2 * i + 0] = coords[2 * i + 0];
929 pxy[2 * i + 1] = coords[2 * i + 1];
930 offset_coords(&pxy[2*i+0], &pxy[2*i+1]);
931 }
932 v_fillarea(npoints, pxy);
933 sfree(pxy);
934#endif
935 }
936
937 /* draw outlines last so they're not covered by the fill */
938 assert(outlinecolor >= 0);
939 rb_color(outlinecolor);
940
941 for(int i = 1; i < npoints; ++i)
546 { 942 {
547 int x1, y1, x2, y2, x3, y3; 943 int x1, y1, x2, y2;
548 x1 = coords[0]; 944 x1 = coords[2 * (i - 1)];
549 y1 = coords[1]; 945 y1 = coords[2 * (i - 1) + 1];
550 x2 = coords[(i - 1) * 2]; 946 x2 = coords[2 * i];
551 y2 = coords[(i - 1) * 2 + 1]; 947 y2 = coords[2 * i + 1];
552 x3 = coords[i * 2]; 948 if(settings.no_aa)
553 y3 = coords[i * 2 + 1]; 949 {
554 offset_coords(&x1, &y1); 950 offset_coords(&x1, &y1);
555 offset_coords(&x2, &y2); 951 offset_coords(&x2, &y2);
556 offset_coords(&x3, &y3); 952 rb->lcd_drawline(x1, y1,
557 xlcd_filltriangle(x1, y1, 953 x2, y2);
558 x2, y2, 954 }
559 x3, y3); 955 else
956 draw_antialiased_line(rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
560 957
561#ifdef DEBUG_MENU 958#ifdef DEBUG_MENU
562 if(settings.polyanim) 959 if(settings.polyanim)
@@ -565,97 +962,102 @@ static void rb_draw_poly(void *handle, int *coords, int npoints,
565 rb->sleep(HZ/4); 962 rb->sleep(HZ/4);
566 } 963 }
567#endif 964#endif
568#if 0
569 /* debug code */
570 rb->lcd_set_foreground(LCD_RGBPACK(255,0,0));
571 rb->lcd_drawpixel(x1, y1);
572 rb->lcd_drawpixel(x2, y2);
573 rb->lcd_drawpixel(x3, y3);
574 rb->lcd_update();
575 rb->sleep(HZ);
576 rb_color(fillcolor);
577 rb->lcd_drawpixel(x1, y1);
578 rb->lcd_drawpixel(x2, y2);
579 rb->lcd_drawpixel(x3, y3);
580 rb->lcd_update();
581#endif
582 } 965 }
583#else
584 int *pxy = smalloc(sizeof(int) * 2 * npoints + 2);
585 /* copy points, offsetted */
586 for(int i = 0; i < npoints; ++i)
587 {
588 pxy[2 * i + 0] = coords[2 * i + 0];
589 pxy[2 * i + 1] = coords[2 * i + 1];
590 offset_coords(&pxy[2*i+0], &pxy[2*i+1]);
591 }
592 v_fillarea(npoints, pxy);
593 sfree(pxy);
594#endif
595 }
596
597 /* draw outlines last so they're not covered by the fill */
598 assert(outlinecolor >= 0);
599 rb_color(outlinecolor);
600 966
601 for(int i = 1; i < npoints; ++i)
602 {
603 int x1, y1, x2, y2; 967 int x1, y1, x2, y2;
604 x1 = coords[2 * (i - 1)]; 968 x1 = coords[0];
605 y1 = coords[2 * (i - 1) + 1]; 969 y1 = coords[1];
606 x2 = coords[2 * i]; 970 x2 = coords[2 * (npoints - 1)];
607 y2 = coords[2 * i + 1]; 971 y2 = coords[2 * (npoints - 1) + 1];
608 if(settings.no_aa) 972 if(settings.no_aa)
609 { 973 {
610 offset_coords(&x1, &y1); 974 offset_coords(&x1, &y1);
611 offset_coords(&x2, &y2); 975 offset_coords(&x2, &y2);
976
612 rb->lcd_drawline(x1, y1, 977 rb->lcd_drawline(x1, y1,
613 x2, y2); 978 x2, y2);
614 } 979 }
615 else 980 else
616 draw_antialiased_line(x1, y1, x2, y2); 981 draw_antialiased_line(rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
982 }
983 else
984 {
985 LOGF("rb_draw_poly");
617 986
618#ifdef DEBUG_MENU 987 if(fillcolor >= 0)
619 if(settings.polyanim)
620 { 988 {
621 rb->lcd_update(); 989 rb_color(fillcolor);
622 rb->sleep(HZ/4); 990
991 /* serious hack: draw a bunch of triangles between adjacent points */
992 /* this generally works, even with some concave polygons */
993 for(int i = 2; i < npoints; ++i)
994 {
995 int x1, y1, x2, y2, x3, y3;
996 x1 = coords[0];
997 y1 = coords[1];
998 x2 = coords[(i - 1) * 2];
999 y2 = coords[(i - 1) * 2 + 1];
1000 x3 = coords[i * 2];
1001 y3 = coords[i * 2 + 1];
1002 zoom_filltriangle(x1, y1,
1003 x2, y2,
1004 x3, y3);
1005 }
623 } 1006 }
624#endif
625 }
626 1007
627 int x1, y1, x2, y2; 1008 /* draw outlines last so they're not covered by the fill */
628 x1 = coords[0]; 1009 assert(outlinecolor >= 0);
629 y1 = coords[1]; 1010 rb_color(outlinecolor);
630 x2 = coords[2 * (npoints - 1)]; 1011
631 y2 = coords[2 * (npoints - 1) + 1]; 1012 for(int i = 1; i < npoints; ++i)
632 if(settings.no_aa) 1013 {
633 { 1014 int x1, y1, x2, y2;
634 offset_coords(&x1, &y1); 1015 x1 = coords[2 * (i - 1)];
635 offset_coords(&x2, &y2); 1016 y1 = coords[2 * (i - 1) + 1];
1017 x2 = coords[2 * i];
1018 y2 = coords[2 * i + 1];
1019 draw_antialiased_line(zoom_fb, zoom_w, zoom_h, x1, y1, x2, y2);
1020 }
636 1021
637 rb->lcd_drawline(x1, y1, 1022 int x1, y1, x2, y2;
638 x2, y2); 1023 x1 = coords[0];
1024 y1 = coords[1];
1025 x2 = coords[2 * (npoints - 1)];
1026 y2 = coords[2 * (npoints - 1) + 1];
1027 draw_antialiased_line(zoom_fb, zoom_w, zoom_h, x1, y1, x2, y2);
639 } 1028 }
640 else
641 draw_antialiased_line(x1, y1, x2, y2);
642} 1029}
643 1030
644static void rb_draw_circle(void *handle, int cx, int cy, int radius, 1031static void rb_draw_circle(void *handle, int cx, int cy, int radius,
645 int fillcolor, int outlinecolor) 1032 int fillcolor, int outlinecolor)
646{ 1033{
647 LOGF("rb_draw_circle(%d, %d, %d)", cx, cy, radius); 1034 if(!zoom_enabled)
648 offset_coords(&cx, &cy);
649
650 if(fillcolor >= 0)
651 { 1035 {
652 rb_color(fillcolor); 1036 LOGF("rb_draw_circle(%d, %d, %d)", cx, cy, radius);
653 xlcd_fillcircle(cx, cy, radius - 1); 1037 offset_coords(&cx, &cy);
1038
1039 if(fillcolor >= 0)
1040 {
1041 rb_color(fillcolor);
1042 xlcd_fillcircle(cx, cy, radius - 1);
1043 }
1044
1045 assert(outlinecolor >= 0);
1046 rb_color(outlinecolor);
1047 xlcd_drawcircle(cx, cy, radius - 1);
654 } 1048 }
1049 else
1050 {
1051 if(fillcolor >= 0)
1052 {
1053 rb_color(fillcolor);
1054 zoom_fillcircle(cx, cy, radius - 1);
1055 }
655 1056
656 assert(outlinecolor >= 0); 1057 assert(outlinecolor >= 0);
657 rb_color(outlinecolor); 1058 rb_color(outlinecolor);
658 xlcd_drawcircle(cx, cy, radius - 1); 1059 zoom_drawcircle(cx, cy, radius - 1);
1060 }
659} 1061}
660 1062
661struct blitter { 1063struct blitter {
@@ -680,11 +1082,14 @@ static void trim_rect(int *x, int *y, int *w, int *h)
680 x1 = *x + *w; 1082 x1 = *x + *w;
681 y1 = *y + *h; 1083 y1 = *y + *h;
682 1084
1085 int screenw = zoom_enabled ? zoom_w : LCD_WIDTH;
1086 int screenh = zoom_enabled ? zoom_h : LCD_HEIGHT;
1087
683 /* Clip each coordinate at both extremes of the canvas */ 1088 /* Clip each coordinate at both extremes of the canvas */
684 x0 = (x0 < 0 ? 0 : x0 > LCD_WIDTH - 1 ? LCD_WIDTH - 1: x0); 1089 x0 = (x0 < 0 ? 0 : x0 > screenw - 1 ? screenw - 1: x0);
685 x1 = (x1 < 0 ? 0 : x1 > LCD_WIDTH - 1 ? LCD_WIDTH - 1: x1); 1090 x1 = (x1 < 0 ? 0 : x1 > screenw - 1 ? screenw - 1: x1);
686 y0 = (y0 < 0 ? 0 : y0 > LCD_HEIGHT - 1 ? LCD_HEIGHT - 1: y0); 1091 y0 = (y0 < 0 ? 0 : y0 > screenh - 1 ? screenh - 1: y0);
687 y1 = (y1 < 0 ? 0 : y1 > LCD_HEIGHT - 1 ? LCD_HEIGHT - 1: y1); 1092 y1 = (y1 < 0 ? 0 : y1 > screenh - 1 ? screenh - 1: y1);
688 1093
689 /* Transform back into x,y,w,h to return */ 1094 /* Transform back into x,y,w,h to return */
690 *x = x0; 1095 *x = x0;
@@ -723,12 +1128,13 @@ static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
723 { 1128 {
724 int w = bl->bmp.width, h = bl->bmp.height; 1129 int w = bl->bmp.width, h = bl->bmp.height;
725 trim_rect(&x, &y, &w, &h); 1130 trim_rect(&x, &y, &w, &h);
1131 fb_data *fb = zoom_enabled ? zoom_fb : rb->lcd_framebuffer;
726 LOGF("rb_blitter_save(%d, %d, %d, %d)", x, y, w, h); 1132 LOGF("rb_blitter_save(%d, %d, %d, %d)", x, y, w, h);
727 for(int i = 0; i < h; ++i) 1133 for(int i = 0; i < h; ++i)
728 { 1134 {
729 /* copy line-by-line */ 1135 /* copy line-by-line */
730 rb->memcpy(bl->bmp.data + sizeof(fb_data) * i * w, 1136 rb->memcpy(bl->bmp.data + sizeof(fb_data) * i * w,
731 rb->lcd_framebuffer + (y + i) * LCD_WIDTH + x, 1137 fb + (y + i) * LCD_WIDTH + x,
732 w * sizeof(fb_data)); 1138 w * sizeof(fb_data));
733 } 1139 }
734 bl->x = x; 1140 bl->x = x;
@@ -748,9 +1154,24 @@ static void rb_blitter_load(void *handle, blitter *bl, int x, int y)
748 if(x == BLITTER_FROMSAVED) x = bl->x; 1154 if(x == BLITTER_FROMSAVED) x = bl->x;
749 if(y == BLITTER_FROMSAVED) y = bl->y; 1155 if(y == BLITTER_FROMSAVED) y = bl->y;
750 1156
751 offset_coords(&x, &y); 1157 if(!zoom_enabled)
1158 offset_coords(&x, &y);
1159
752 trim_rect(&x, &y, &w, &h); 1160 trim_rect(&x, &y, &w, &h);
753 rb->lcd_bitmap((fb_data*)bl->bmp.data, x, y, w, h); 1161
1162 if(!zoom_enabled)
1163 {
1164 rb->lcd_bitmap((fb_data*)bl->bmp.data, x, y, w, h);
1165 }
1166 else
1167 {
1168 for(int i = 0; i < h; ++i)
1169 {
1170 rb->memcpy(zoom_fb + i * zoom_w + x,
1171 bl->bmp.data + sizeof(fb_data) * i * w,
1172 w * sizeof(fb_data));
1173 }
1174 }
754} 1175}
755 1176
756static bool need_draw_update = false; 1177static bool need_draw_update = false;
@@ -793,11 +1214,17 @@ static void rb_start_draw(void *handle)
793static void rb_end_draw(void *handle) 1214static void rb_end_draw(void *handle)
794{ 1215{
795 (void) handle; 1216 (void) handle;
1217 if(!zoom_enabled)
1218 {
1219 LOGF("rb_end_draw");
796 1220
797 LOGF("rb_end_draw"); 1221 if(need_draw_update)
798 1222 rb->lcd_update_rect(MAX(0, ud_l), MAX(0, ud_u), MIN(LCD_WIDTH, ud_r - ud_l), MIN(LCD_HEIGHT, ud_d - ud_u));
799 if(need_draw_update) 1223 }
800 rb->lcd_update_rect(MAX(0, ud_l), MAX(0, ud_u), MIN(LCD_WIDTH, ud_r - ud_l), MIN(LCD_HEIGHT, ud_d - ud_u)); 1224 else
1225 {
1226 /* stubbed */
1227 }
801} 1228}
802 1229
803static char *titlebar = NULL; 1230static char *titlebar = NULL;
@@ -824,7 +1251,8 @@ static void draw_title(void)
824 rb_unclip(NULL); 1251 rb_unclip(NULL);
825 1252
826 int h; 1253 int h;
827 rb->lcd_setfont(FONT_UI); 1254 cur_font = FONT_UI;
1255 rb->lcd_setfont(cur_font);
828 rb->lcd_getstringsize(str, NULL, &h); 1256 rb->lcd_getstringsize(str, NULL, &h);
829 1257
830 rb->lcd_set_foreground(BG_COLOR); 1258 rb->lcd_set_foreground(BG_COLOR);
@@ -866,6 +1294,73 @@ const drawing_api rb_drawing = {
866 NULL, 1294 NULL,
867}; 1295};
868 1296
1297/* render to a virtual framebuffer and let the user pan (but not make any moves) */
1298static void zoom(void)
1299{
1300 zoom_w = LCD_WIDTH * ZOOM_FACTOR, zoom_h = LCD_HEIGHT * ZOOM_FACTOR;
1301
1302 zoom_clipu = 0;
1303 zoom_clipd = zoom_h;
1304 zoom_clipl = 0;
1305 zoom_clipr = zoom_w;
1306
1307 midend_size(me, &zoom_w, &zoom_h, TRUE);
1308
1309 /* allocate a framebuffer */
1310 zoom_fb = smalloc(zoom_w * zoom_h * sizeof(fb_data));
1311 zoom_enabled = true;
1312
1313 /* draws go to the enlarged framebuffer */
1314 midend_force_redraw(me);
1315
1316 int x = 0, y = 0;
1317
1318 rb->lcd_bitmap_part(zoom_fb, x, y, STRIDE(SCREEN_MAIN, zoom_w, zoom_h),
1319 0, 0, LCD_WIDTH, LCD_HEIGHT);
1320 rb->lcd_update();
1321
1322 /* pan around the image */
1323 while(1)
1324 {
1325 int button = rb->button_get(true);
1326 switch(button)
1327 {
1328 case BTN_UP:
1329 y -= PAN_Y; /* clamped later */
1330 break;
1331 case BTN_DOWN:
1332 y += PAN_Y; /* clamped later */
1333 break;
1334 case BTN_LEFT:
1335 x -= PAN_X; /* clamped later */
1336 break;
1337 case BTN_RIGHT:
1338 x += PAN_X; /* clamped later */
1339 break;
1340 case BTN_PAUSE:
1341 zoom_enabled = false;
1342 sfree(zoom_fb);
1343 fix_size();
1344 return;
1345 default:
1346 break;
1347 }
1348
1349 if(y < 0)
1350 y = 0;
1351 if(x < 0)
1352 x = 0;
1353 if(y + LCD_HEIGHT >= zoom_h)
1354 y = zoom_h - LCD_HEIGHT;
1355 if(x + LCD_WIDTH >= zoom_w)
1356 x = zoom_w - LCD_WIDTH;
1357
1358 rb->lcd_bitmap_part(zoom_fb, x, y, STRIDE(SCREEN_MAIN, zoom_w, zoom_h),
1359 0, 0, LCD_WIDTH, LCD_HEIGHT);
1360 rb->lcd_update();
1361 }
1362}
1363
869void frontend_default_color(frontend *fe, float *out) 1364void frontend_default_color(frontend *fe, float *out)
870{ 1365{
871 *out++ = BG_R; 1366 *out++ = BG_R;
@@ -1123,7 +1618,8 @@ static bool config_menu(void)
1123 char *title; 1618 char *title;
1124 config_item *config = midend_get_config(me, CFG_SETTINGS, &title); 1619 config_item *config = midend_get_config(me, CFG_SETTINGS, &title);
1125 1620
1126 rb->lcd_setfont(FONT_UI); 1621 cur_font = FONT_UI;
1622 rb->lcd_setfont(cur_font);
1127 1623
1128 bool success = false; 1624 bool success = false;
1129 1625
@@ -1318,7 +1814,8 @@ static void full_help(const char *name)
1318 rb->lcd_set_foreground(LCD_WHITE); 1814 rb->lcd_set_foreground(LCD_WHITE);
1319 rb->lcd_set_background(LCD_BLACK); 1815 rb->lcd_set_background(LCD_BLACK);
1320 unload_fonts(); 1816 unload_fonts();
1321 rb->lcd_setfont(FONT_UI); 1817 cur_font = FONT_UI;
1818 rb->lcd_setfont(cur_font);
1322 1819
1323 char *buf = smalloc(help_text_len); 1820 char *buf = smalloc(help_text_len);
1324 LZ4_decompress_tiny(help_text, buf, help_text_len); 1821 LZ4_decompress_tiny(help_text, buf, help_text_len);
@@ -1354,7 +1851,7 @@ static void bench_aa(void)
1354 int i = 0; 1851 int i = 0;
1355 while(*rb->current_tick < next) 1852 while(*rb->current_tick < next)
1356 { 1853 {
1357 draw_antialiased_line(0, 0, 20, 31); 1854 draw_antialiased_line(rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, 0, 0, 20, 31);
1358 ++i; 1855 ++i;
1359 } 1856 }
1360 rb->splashf(HZ, "%d AA lines/sec", i); 1857 rb->splashf(HZ, "%d AA lines/sec", i);
@@ -1460,7 +1957,7 @@ static int pausemenu_cb(int action, const struct menu_item_ex *this_item)
1460 if(!midend_get_presets(me, NULL)->n_entries) 1957 if(!midend_get_presets(me, NULL)->n_entries)
1461 return ACTION_EXIT_MENUITEM; 1958 return ACTION_EXIT_MENUITEM;
1462 break; 1959 break;
1463 case 10: 1960 case 11:
1464#if defined(FOR_REAL) && defined(DEBUG_MENU) 1961#if defined(FOR_REAL) && defined(DEBUG_MENU)
1465 if(debug_mode) 1962 if(debug_mode)
1466 break; 1963 break;
@@ -1468,7 +1965,7 @@ static int pausemenu_cb(int action, const struct menu_item_ex *this_item)
1468#else 1965#else
1469 break; 1966 break;
1470#endif 1967#endif
1471 case 11: 1968 case 12:
1472 if(!midend_which_game(me)->can_configure) 1969 if(!midend_which_game(me)->can_configure)
1473 return ACTION_EXIT_MENUITEM; 1970 return ACTION_EXIT_MENUITEM;
1474 break; 1971 break;
@@ -1507,6 +2004,7 @@ static int pause_menu(void)
1507 "Undo", 2004 "Undo",
1508 "Redo", 2005 "Redo",
1509 "Solve", 2006 "Solve",
2007 "Zoom In",
1510 "Quick Help", 2008 "Quick Help",
1511 "Extensive Help", 2009 "Extensive Help",
1512 "Playback Control", 2010 "Playback Control",
@@ -1568,15 +2066,18 @@ static int pause_menu(void)
1568 break; 2066 break;
1569 } 2067 }
1570 case 6: 2068 case 6:
1571 quick_help(); 2069 zoom();
1572 break; 2070 break;
1573 case 7: 2071 case 7:
1574 full_help(midend_which_game(me)->name); 2072 quick_help();
1575 break; 2073 break;
1576 case 8: 2074 case 8:
1577 playback_control(NULL); 2075 full_help(midend_which_game(me)->name);
1578 break; 2076 break;
1579 case 9: 2077 case 9:
2078 playback_control(NULL);
2079 break;
2080 case 10:
1580 if(presets_menu()) 2081 if(presets_menu())
1581 { 2082 {
1582 midend_new_game(me); 2083 midend_new_game(me);
@@ -1586,12 +2087,12 @@ static int pause_menu(void)
1586 quit = true; 2087 quit = true;
1587 } 2088 }
1588 break; 2089 break;
1589 case 10: 2090 case 11:
1590#ifdef DEBUG_MENU 2091#ifdef DEBUG_MENU
1591 debug_menu(); 2092 debug_menu();
1592#endif 2093#endif
1593 break; 2094 break;
1594 case 11: 2095 case 12:
1595 if(config_menu()) 2096 if(config_menu())
1596 { 2097 {
1597 midend_new_game(me); 2098 midend_new_game(me);
@@ -1601,9 +2102,9 @@ static int pause_menu(void)
1601 quit = true; 2102 quit = true;
1602 } 2103 }
1603 break; 2104 break;
1604 case 12:
1605 return -2;
1606 case 13: 2105 case 13:
2106 return -2;
2107 case 14:
1607 return -3; 2108 return -3;
1608 default: 2109 default:
1609 break; 2110 break;
@@ -1846,7 +2347,8 @@ static size_t giant_buffer_len = 0; /* set on start */
1846static void fix_size(void) 2347static void fix_size(void)
1847{ 2348{
1848 int w = LCD_WIDTH, h = LCD_HEIGHT, h_x; 2349 int w = LCD_WIDTH, h = LCD_HEIGHT, h_x;
1849 rb->lcd_setfont(FONT_UI); 2350 cur_font = FONT_UI;
2351 rb->lcd_setfont(cur_font);
1850 rb->lcd_getstringsize("X", NULL, &h_x); 2352 rb->lcd_getstringsize("X", NULL, &h_x);
1851 h -= h_x; 2353 h -= h_x;
1852 midend_size(me, &w, &h, TRUE); 2354 midend_size(me, &w, &h, TRUE);