Move the PCM/audio playback part of SDL into the target tree.
[kugel-rb.git] / apps / plugins / goban / display.c
blob8c180397591529b920ee28e72bd29a55c853cac3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007-2009 Joshua Simmons <mud at majidejima dot com>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "board.h"
23 #include "goban.h"
24 #include "display.h"
25 #include "game.h"
26 #include "sgf.h"
28 /* for xlcd_filltriangle */
29 #include "lib/xlcd.h"
31 unsigned int intersection_size = 0;
33 #define LINE_OFFSET (intersection_size / 2)
35 /* pixel offsets for the board on the LCD */
36 int board_x = 0;
37 int board_y = 0;
38 int board_pixel_width = 0;
39 int board_pixel_height = 0;
41 /* current cursor position in board coordinates (intersections, not
42 pixels) */
43 unsigned short cursor_pos = POS (0, 0);
45 /* we way need to "move" our notion of which intersections to draw when
46 the cursor moves, since we can be zoomed in (and often will be) this is
47 used to signal when we need to do that */
48 unsigned short last_cursor_pos = INVALID_POS;
49 unsigned int last_int_size = MAX_INT_SIZE + 1;
51 unsigned int min_x_int = 0;
52 unsigned int min_y_int = 0;
53 unsigned int num_x_ints = 0;
54 unsigned int num_y_ints = 0;
56 int extend_t = 0, extend_b = 0, extend_l = 0, extend_r = 0;
58 bool draw_variations = true;
59 unsigned int saved_circle_size = 0;
60 bool has_comment = false;
62 unsigned char display_marks[MAX_BOARD_SIZE * MAX_BOARD_SIZE];
65 /* function prototypes */
67 static int pixel_x (unsigned short pos);
68 static int pixel_y (unsigned short pos);
70 static void draw_circle (int c_x, int c_y, int r, bool filled);
72 static void draw_cursor (unsigned short pos);
73 static void draw_stone_raw (int pixel_x, int pixel_y, bool black);
74 static void draw_stone (unsigned short pos, bool black);
75 static void draw_all_stones (void);
77 static void draw_hoshi (unsigned short pos);
78 static void draw_footer (void);
79 static void draw_all_marks (void);
80 static void draw_all_hoshi (void);
82 static unsigned int unzoomed_int_size (void);
83 static void cursor_updated (void);
85 void
86 clear_marks_display (void)
88 rb->memset (display_marks, ' ', sizeof (display_marks));
89 has_comment = false;
92 void
93 set_mark_display (unsigned short pos, unsigned char mark_char)
95 if (!on_board (pos))
97 return;
100 if ((mark_char == 'b' || mark_char == 'w') &&
101 display_marks[I (pos) + J (pos) * board_width] != ' ')
103 /* don't overwrite real board marks with last-move or variation
104 marks */
105 return;
108 display_marks[I (pos) + J (pos) * board_width] = mark_char;
112 void
113 set_comment_display (bool new_val)
115 has_comment = new_val;
119 static void
120 draw_all_marks (void)
122 unsigned int x, y;
123 for (x = MIN_X; x < MAX_X; ++x)
125 for (y = MIN_Y; y < MAX_Y; ++y)
127 if (display_marks[x + y * board_width] != ' ')
129 #if LCD_DEPTH > 1
130 if (display_marks[x + y * board_width] != 'b' &&
131 display_marks[x + y * board_width] != 'w')
133 rb->lcd_set_foreground (MARK_COLOR);
135 else
137 rb->lcd_set_foreground (CURSOR_COLOR);
139 rb->lcd_set_drawmode (DRMODE_FG);
140 #else
141 rb->lcd_set_drawmode (DRMODE_FG + DRMODE_COMPLEMENT);
142 #endif
144 if (display_marks[x + y * board_width] & (1 << 7))
146 char to_display[2];
147 int width, height;
149 to_display[0] =
150 display_marks[x + y * board_width] & (~(1 << 7));
151 to_display[1] = '\0';
153 rb->lcd_getstringsize (to_display, &width, &height);
155 int display_x =
156 pixel_x (POS (x, y)) + LINE_OFFSET - (width / 2);
157 int display_y =
158 pixel_y (POS (x, y)) + LINE_OFFSET - (height / 2);
160 if (display_x < 0)
162 display_x = 0;
165 if (display_y < 0)
167 display_y = 0;
170 if (display_x + width >= LCD_WIDTH)
172 display_x = LCD_WIDTH - 1 - width;
175 if (display_y + height >= LCD_HEIGHT)
177 display_y = LCD_HEIGHT - 1 - height;
180 rb->lcd_putsxy (display_x, display_y, to_display);
181 continue;
184 switch (display_marks[x + y * board_width])
186 /* moves, 'mark', 'square' */
187 case 'b':
188 case 'w':
189 if (intersection_size <= 5)
191 DEBUGF ("screen is too small to mark current move\n");
192 break;
194 case 'm':
195 if (intersection_size <= 5)
197 rb->lcd_drawpixel (pixel_x (POS (x, y)) + LINE_OFFSET +
199 pixel_y (POS (x, y)) + LINE_OFFSET +
201 rb->lcd_drawpixel (pixel_x (POS (x, y)) + LINE_OFFSET -
203 pixel_y (POS (x, y)) + LINE_OFFSET -
206 else
208 rb->lcd_drawrect (pixel_x (POS (x, y)) + LINE_OFFSET -
209 intersection_size / 6,
210 pixel_y (POS (x, y)) + LINE_OFFSET -
211 intersection_size / 6,
212 (intersection_size / 6) * 2 + 1,
213 (intersection_size / 6) * 2 + 1);
215 break;
216 case 's':
217 if (intersection_size <= 5)
219 rb->lcd_drawpixel (pixel_x (POS (x, y)) + LINE_OFFSET +
221 pixel_y (POS (x, y)) + LINE_OFFSET +
223 rb->lcd_drawpixel (pixel_x (POS (x, y)) + LINE_OFFSET -
225 pixel_y (POS (x, y)) + LINE_OFFSET -
228 else
230 rb->lcd_fillrect (pixel_x (POS (x, y)) + LINE_OFFSET -
231 intersection_size / 6,
232 pixel_y (POS (x, y)) + LINE_OFFSET -
233 intersection_size / 6,
234 (intersection_size / 6) * 2 + 1,
235 (intersection_size / 6) * 2 + 1);
237 break;
239 case 'c':
240 if (intersection_size > 7)
242 draw_circle (pixel_x (POS (x, y)) + LINE_OFFSET,
243 pixel_y (POS (x, y)) + LINE_OFFSET,
244 (intersection_size - 1) / 4, true);
245 break;
248 /* purposely don't break here, draw small the same as
249 a triangle */
251 case 't':
252 if (intersection_size <= 7)
254 rb->lcd_drawpixel (pixel_x (POS (x, y)) + LINE_OFFSET -
256 pixel_y (POS (x, y)) + LINE_OFFSET +
258 rb->lcd_drawpixel (pixel_x (POS (x, y)) + LINE_OFFSET +
260 pixel_y (POS (x, y)) + LINE_OFFSET -
263 else
265 xlcd_filltriangle (pixel_x (POS (x, y)) + LINE_OFFSET,
266 pixel_y (POS (x, y)) + LINE_OFFSET -
267 intersection_size / 4,
268 pixel_x (POS (x, y)) + LINE_OFFSET +
269 intersection_size / 4,
270 pixel_y (POS (x, y)) + LINE_OFFSET +
271 intersection_size / 4,
272 pixel_x (POS (x, y)) + LINE_OFFSET -
273 intersection_size / 4,
274 pixel_y (POS (x, y)) + LINE_OFFSET +
275 intersection_size / 4);
277 break;
278 default:
279 DEBUGF ("tried to display unknown mark '%c' %d\n",
280 display_marks[x + y * board_width],
281 display_marks[x + y * board_width]);
282 break;
285 rb->lcd_set_drawmode (DRMODE_SOLID);
286 /* don't have to undo the colors for LCD_DEPTH > 1, most
287 functions assume bg and fg get clobbered */
294 static void
295 draw_circle (int c_x, int c_y, int r, bool filled)
297 int f = 1 - r;
298 int x = 0;
299 int y = r;
301 /* draw the points on the axes to make the loop easier */
302 rb->lcd_drawpixel (c_x, c_y + r);
303 rb->lcd_drawpixel (c_x, c_y - r);
305 if (filled)
307 rb->lcd_hline (c_x - r, c_x + r, c_y);
309 else
311 rb->lcd_drawpixel (c_x + r, c_y);
312 rb->lcd_drawpixel (c_x - r, c_y);
315 /* Now walk from the very top of the circle to 1/8th of the way around
316 to the right. For each point, draw the 8 symmetrical points. */
317 while (x < y)
319 /* walk one pixel to the right */
320 ++x;
322 /* And then adjust our discriminant, and adjust y if we've
323 ventured outside of the circle. This boils down to walking a
324 tightrope between being inside and outside the circle. The
325 updating functions are taken from expanding the discriminant
326 function f(x, y) = x^2 + y^2 - r^2 after substituting in x + 1
327 and y - 1 and then subtracting out f(x, y) */
328 if (f <= 0)
330 f += 2 * x + 1;
332 else
334 --y;
335 f += (x - y) * 2 + 1;
338 if (filled)
340 /* each line takes care of 2 points on the circle so we only
341 need 4 */
342 rb->lcd_hline (c_x - y, c_x + y, c_y + x);
343 rb->lcd_hline (c_x - y, c_x + y, c_y - x);
344 rb->lcd_hline (c_x - x, c_x + x, c_y + y);
345 rb->lcd_hline (c_x - x, c_x + x, c_y - y);
347 else
349 /* Draw all 8 symmetrical points */
350 rb->lcd_drawpixel (c_x + x, c_y + y);
351 rb->lcd_drawpixel (c_x + y, c_y + x);
352 rb->lcd_drawpixel (c_x + y, c_y - x);
353 rb->lcd_drawpixel (c_x + x, c_y - y);
354 rb->lcd_drawpixel (c_x - x, c_y + y);
355 rb->lcd_drawpixel (c_x - y, c_y + x);
356 rb->lcd_drawpixel (c_x - y, c_y - x);
357 rb->lcd_drawpixel (c_x - x, c_y - y);
363 void
364 draw_screen_display (void)
366 #if LCD_DEPTH > 1
367 int saved_fg = rb->lcd_get_foreground ();
368 int saved_bg = rb->lcd_get_background ();
369 #endif
370 int saved_drmode = rb->lcd_get_drawmode ();
372 if (cursor_pos != last_cursor_pos || intersection_size != last_int_size)
374 cursor_updated ();
377 #if LCD_DEPTH > 1
378 rb->lcd_set_backdrop (NULL);
380 rb->lcd_set_foreground (BOARD_COLOR);
381 rb->lcd_set_background (BACKGROUND_COLOR);
382 rb->lcd_set_drawmode (DRMODE_SOLID);
384 #else
385 rb->lcd_set_drawmode (DRMODE_SOLID + DRMODE_INVERSEVID);
386 #endif
388 rb->lcd_clear_display ();
390 rb->lcd_fillrect (pixel_x (POS (MIN_X, MIN_Y)),
391 pixel_y (POS (MIN_X, MIN_Y)),
392 (MAX_X - MIN_X) * intersection_size,
393 (MAX_Y - MIN_Y) * intersection_size);
395 #if LCD_DEPTH > 1
396 rb->lcd_set_foreground (LINE_COLOR);
397 #else
398 rb->lcd_set_drawmode (DRMODE_SOLID);
399 #endif
401 unsigned int i;
402 for (i = MIN_Y; i < MAX_Y; ++i)
404 rb->lcd_hline (pixel_x (POS (MIN_X, i)) + LINE_OFFSET + extend_l,
405 pixel_x (POS (MAX_X - 1, i)) + LINE_OFFSET + extend_r,
406 pixel_y (POS (MIN_X, i)) + LINE_OFFSET);
409 for (i = MIN_X; i < MAX_X; ++i)
411 rb->lcd_vline (pixel_x (POS (i, MIN_Y)) + LINE_OFFSET,
412 pixel_y (POS (i, MIN_Y)) + LINE_OFFSET + extend_t,
413 pixel_y (POS (i, MAX_Y - 1)) + LINE_OFFSET + extend_b);
416 draw_all_hoshi ();
417 draw_all_stones ();
418 draw_cursor (cursor_pos);
420 if (draw_variations)
422 mark_child_variations_sgf ();
425 draw_all_marks ();
427 draw_footer ();
428 rb->lcd_update ();
430 #if LCD_DEPTH > 1
431 rb->lcd_set_foreground (saved_fg);
432 rb->lcd_set_background (saved_bg);
433 #endif
434 rb->lcd_set_drawmode (saved_drmode);
439 #if defined(GBN_WIDE_SCREEN)
441 /* the size of the string, in pixels, when drawn vertically */
442 static void
443 vert_string_size (char *string, int *width, int *height)
445 int temp_width = 0;
446 int temp_height = 0;
448 int ret_width = 0;
449 int ret_height = 0;
451 char temp_buffer[2];
453 temp_buffer[0] = temp_buffer[1] = 0;
455 if (!string)
457 return;
460 while (*string)
462 temp_buffer[0] = *string;
463 rb->lcd_getstringsize (temp_buffer, &temp_width, &temp_height);
465 ret_height += temp_height;
467 if (ret_width < temp_width)
469 ret_width = temp_width;
472 ++string;
475 if (width)
477 *width = ret_width;
480 if (height)
482 *height = ret_height;
486 static void
487 putsxy_vertical (int x, int y, int width, char *str)
489 int temp_width = 0;
490 int temp_height = 0;
491 char temp_buffer[2];
493 temp_buffer[0] = temp_buffer[1] = 0;
495 if (!str)
497 return;
500 while (*str)
502 temp_buffer[0] = *str;
503 rb->lcd_getstringsize (temp_buffer, &temp_width, &temp_height);
504 DEBUGF ("putting %s at %d %d\n", temp_buffer,
505 x + (width - temp_width) / 2, y);
506 rb->lcd_putsxy (x + (width - temp_width) / 2, y, temp_buffer);
507 y += temp_height;
508 ++str;
512 #endif /* GBN_WIDE_SCREEN */
515 static void
516 draw_footer (void)
518 char captures_buffer[16];
519 char display_flags[16] = "";
520 int size_x, size_y;
521 int vert_x, vert_y;
523 (void) vert_x;
524 (void) vert_y;
526 #if LCD_DEPTH > 1
527 rb->lcd_set_background (BACKGROUND_COLOR);
528 rb->lcd_set_foreground (BLACK_COLOR);
529 #else
530 rb->lcd_set_drawmode (DRMODE_SOLID + DRMODE_INVERSEVID);
531 #endif
533 rb->snprintf (captures_buffer, sizeof (captures_buffer),
534 "%d", white_captures);
537 rb->lcd_getstringsize (captures_buffer, &size_x, &size_y);
538 #if defined(GBN_TALL_SCREEN)
539 rb->lcd_putsxy (size_y + 2, LCD_HEIGHT - size_y, captures_buffer);
540 #else
541 vert_string_size (captures_buffer, &vert_x, &vert_y);
542 if (board_pixel_width + size_x <= LCD_WIDTH)
544 rb->lcd_putsxy (LCD_WIDTH - size_x - 1, vert_x + 2, captures_buffer);
546 else
548 putsxy_vertical (LCD_WIDTH - vert_x - 1, vert_x + 2, vert_x,
549 captures_buffer);
551 #endif
553 #if LCD_DEPTH == 1
554 rb->lcd_set_drawmode (DRMODE_SOLID);
555 #endif
557 #if defined(GBN_TALL_SCREEN)
558 draw_circle (size_y / 2,
559 LCD_HEIGHT - (size_y / 2), (size_y - 1) / 2, true);
561 #if LCD_DEPTH == 1
562 rb->lcd_set_drawmode (DRMODE_SOLID + DRMODE_INVERSEVID);
563 draw_circle (size_y / 2,
564 LCD_HEIGHT - (size_y / 2), (size_y - 1) / 2, false);
565 #endif /* LCD_DEPTH */
567 #else /* !GBN_TALL_SCREEN */
568 draw_circle (LCD_WIDTH - 1 - vert_x / 2,
569 (vert_x / 2), (vert_x - 1) / 2, true);
571 #if LCD_DEPTH == 1
572 rb->lcd_set_drawmode (DRMODE_SOLID + DRMODE_INVERSEVID);
573 draw_circle (LCD_WIDTH - 1 - vert_x / 2,
574 (vert_x / 2), (vert_x - 1) / 2, false);
575 #endif /* LCD_DEPTH */
577 #endif /* GBN_TALL_SCREEN */
580 #if LCD_DEPTH > 1
581 rb->lcd_set_foreground (WHITE_COLOR);
582 #endif
583 rb->snprintf (captures_buffer, sizeof (captures_buffer),
584 "%d", black_captures);
586 rb->lcd_getstringsize (captures_buffer, &size_x, &size_y);
587 #if defined(GBN_TALL_SCREEN)
588 rb->lcd_putsxy (LCD_WIDTH - (size_y + 1) - size_x,
589 LCD_HEIGHT - size_y, captures_buffer);
591 draw_circle (LCD_WIDTH - (size_y / 2),
592 LCD_HEIGHT - (size_y / 2), (size_y - 1) / 2, true);
593 #else
594 vert_string_size (captures_buffer, &vert_x, &vert_y);
595 if (board_pixel_width + size_x <= LCD_WIDTH)
597 rb->lcd_putsxy (LCD_WIDTH - size_x - 1,
598 LCD_HEIGHT - vert_x - size_y - 3, captures_buffer);
600 else
602 putsxy_vertical (LCD_WIDTH - vert_x - 1,
603 LCD_HEIGHT - vert_x - 3 - vert_y,
604 vert_x, captures_buffer);
607 draw_circle (LCD_WIDTH - 1 - vert_x / 2,
608 LCD_HEIGHT - 1 - vert_x / 2, (vert_x - 1) / 2, true);
609 #endif
612 #if LCD_DEPTH > 1
613 rb->lcd_set_foreground (BLACK_COLOR);
614 #endif
616 if (has_comment)
618 rb->strcat (display_flags, "C");
621 if (has_more_nodes_sgf ())
623 rb->strcat (display_flags, "+");
626 if (num_variations_sgf () > 1)
628 rb->strcat (display_flags, "*");
633 rb->snprintf (captures_buffer, sizeof (captures_buffer),
634 "%d%s", move_num, display_flags);
636 rb->lcd_getstringsize (captures_buffer, &size_x, &size_y);
637 #if defined(GBN_TALL_SCREEN)
638 rb->lcd_putsxy ((LCD_WIDTH - size_x) / 2,
639 LCD_HEIGHT - size_y, captures_buffer);
640 #else
641 if (board_pixel_width + size_x <= LCD_WIDTH)
643 rb->lcd_putsxy (LCD_WIDTH - size_x - 1,
644 (LCD_HEIGHT - size_y) / 2, captures_buffer);
646 else
648 vert_string_size (captures_buffer, &vert_x, &vert_y);
649 putsxy_vertical (LCD_WIDTH - vert_x - 1,
650 (LCD_HEIGHT - vert_y) / 2, vert_x, captures_buffer);
652 #endif
655 rb->lcd_set_drawmode (DRMODE_SOLID);
664 static int
665 pixel_x (unsigned short pos)
667 return board_x + (I (pos) - min_x_int) * intersection_size;
670 static int
671 pixel_y (unsigned short pos)
673 return board_y + (J (pos) - min_y_int) * intersection_size;
678 void
679 move_display (unsigned short pos)
681 if (!on_board (pos))
683 return;
686 while ((unsigned) I (pos) >= REAL_MAX_X)
688 cursor_pos = EAST (cursor_pos);
689 cursor_updated ();
691 while ((unsigned) I (pos) < REAL_MIN_X)
693 cursor_pos = WEST (cursor_pos);
694 cursor_updated ();
697 while ((unsigned) J (pos) >= REAL_MAX_Y)
699 cursor_pos = SOUTH (cursor_pos);
700 cursor_updated ();
702 while ((unsigned) J (pos) < REAL_MIN_Y)
704 cursor_pos = NORTH (cursor_pos);
705 cursor_updated ();
710 static void
711 cursor_updated (void)
713 if (!on_board(cursor_pos))
715 cursor_pos = WRAP (cursor_pos);
718 if (intersection_size != last_int_size ||
719 ((unsigned) I (cursor_pos)) < REAL_MIN_X + 1 ||
720 ((unsigned) I (cursor_pos)) > REAL_MAX_X - 2 ||
721 ((unsigned) J (cursor_pos)) < REAL_MIN_Y + 1 ||
722 ((unsigned) J (cursor_pos)) > REAL_MAX_Y - 2)
724 if ((unsigned) I (cursor_pos) < (num_x_ints / 2))
726 min_x_int = 0;
728 else
730 min_x_int = min (I (cursor_pos) - (num_x_ints / 2),
731 board_width - num_x_ints);
734 if ((unsigned) J (cursor_pos) < (num_y_ints / 2))
736 min_y_int = 0;
738 else
741 min_y_int = min (J (cursor_pos) - (num_y_ints / 2),
742 board_height - num_y_ints);
746 /* these are used in line drawing to extend the lines if there is more
747 board in that direction */
748 if (MIN_X)
750 extend_l = -1 * LINE_OFFSET;
752 else
754 extend_l = 0;
757 if (MIN_Y)
759 extend_t = -1 * LINE_OFFSET;
761 else
763 extend_t = 0;
766 if (MAX_X != board_width)
768 extend_r = LINE_OFFSET;
770 else
772 extend_r = 0;
775 if (MAX_Y != board_height)
777 extend_b = LINE_OFFSET;
779 else
781 extend_b = 0;
784 last_cursor_pos = cursor_pos;
785 last_int_size = intersection_size;
788 static unsigned int
789 unzoomed_int_size (void)
791 int int_size = min ((LCD_BOARD_WIDTH / board_width),
792 (LCD_BOARD_HEIGHT / board_height));
794 if (!(int_size & 1))
796 --int_size;
799 if (int_size < 0)
801 int_size = 1;
804 return max(int_size, MIN_INT_SIZE);
807 unsigned int
808 current_zoom_display (void)
810 return (intersection_size - unzoomed_int_size ()) / 2 + 1;
813 unsigned int
814 max_zoom_display (void)
816 return (MAX_INT_SIZE - unzoomed_int_size ()) / 2 + 1;
819 unsigned int
820 min_zoom_display (void)
822 if (MIN_INT_SIZE >= unzoomed_int_size())
824 return (MIN_INT_SIZE - unzoomed_int_size ()) / 2 + 1;
826 else
828 return 1;
832 void
833 set_zoom_display (unsigned int zoom_level)
835 unsigned int unzoomed = unzoomed_int_size ();
837 if (saved_circle_size < MIN_INT_SIZE ||
838 saved_circle_size > MAX_INT_SIZE)
840 saved_circle_size = MIN_DEFAULT_INT_SIZE;
843 if (zoom_level == 0)
845 /* default zoom, we get to set it however we want */
846 intersection_size = max (unzoomed, saved_circle_size);
848 else
850 intersection_size = unzoomed + 2 * (zoom_level - 1);
853 if (intersection_size > MAX_INT_SIZE)
855 intersection_size = MAX_INT_SIZE;
858 /* now intersection_size has been set appropriately, so set up all of
859 the derived values used for display */
861 num_x_ints = min (LCD_BOARD_WIDTH / intersection_size, board_width);
862 num_y_ints = min (LCD_BOARD_HEIGHT / intersection_size, board_height);
864 board_pixel_width = num_x_ints * intersection_size;
865 board_pixel_height = num_y_ints * intersection_size;
867 #if defined(GBN_TALL_SCREEN)
868 board_x = (LCD_WIDTH - board_pixel_width) / 2;
869 board_y = 0;
870 #elif defined(GBN_WIDE_SCREEN)
871 board_x = 0;
872 board_y = (LCD_HEIGHT - board_pixel_height) / 2;
873 #else
874 #error screen dimensions have not been evaluated properly
875 #endif
879 /* Call every time the board size might have changed! */
880 void
881 setup_display (void)
883 set_zoom_display (0); /* 0 means set to default */
885 /* The cursor starts out in the top right of the board
886 * (on the hoshi point for most board sizes), unless the board
887 * is really small in which case the cursor starts at the center
888 * of the board.
890 int start_x, start_y;
891 if (board_width >= 7)
893 start_x = board_width - 4;
895 else
897 start_x = board_width / 2;
900 if (board_height >= 7)
902 start_y = 3;
904 else
906 start_y = board_height / 2;
908 cursor_pos = POS (start_x, start_y);
909 last_cursor_pos = INVALID_POS;
910 last_int_size = -1;
912 clear_marks_display ();
915 static void
916 draw_cursor (unsigned short pos)
918 if (!on_board (pos))
920 return;
923 #if LCD_DEPTH > 1
924 rb->lcd_set_foreground (CURSOR_COLOR);
925 #else
926 rb->lcd_set_drawmode (DRMODE_COMPLEMENT);
927 #endif
929 rb->lcd_drawrect (pixel_x (pos),
930 pixel_y (pos), intersection_size, intersection_size);
932 rb->lcd_set_drawmode (DRMODE_SOLID);
935 static void
936 draw_stone_raw (int pixel_x, int pixel_y, bool black)
938 #if LCD_DEPTH > 1
939 rb->lcd_set_foreground (black ? BLACK_COLOR : WHITE_COLOR);
940 #else
941 if (black)
943 rb->lcd_set_drawmode (DRMODE_SOLID);
945 else
947 rb->lcd_set_drawmode (DRMODE_SOLID + DRMODE_INVERSEVID);
949 #endif
951 draw_circle (pixel_x + LINE_OFFSET,
952 pixel_y + LINE_OFFSET, LINE_OFFSET, true);
954 #if defined(OUTLINE_STONES)
955 #if LCD_DEPTH > 1
956 rb->lcd_set_foreground (black ? WHITE_COLOR : BLACK_COLOR);
957 #else
958 if (black)
960 rb->lcd_set_drawmode (DRMODE_SOLID + DRMODE_INVERSEVID);
962 else
964 rb->lcd_set_drawmode (DRMODE_SOLID);
966 #endif /* LCD_DEPTH > 1 */
968 if (!black)
970 draw_circle (pixel_x + LINE_OFFSET,
971 pixel_y + LINE_OFFSET, LINE_OFFSET, false);
974 #endif /* OUTLINE_STONES */
976 rb->lcd_set_drawmode (DRMODE_SOLID);
980 static void
981 draw_stone (unsigned short pos, bool black)
983 if (!on_board (pos))
985 return;
988 draw_stone_raw (pixel_x (pos), pixel_y (pos), black);
992 static void
993 draw_all_stones (void)
995 unsigned int x, y;
996 unsigned short temp_pos;
998 for (x = MIN_X; x < MAX_X; ++x)
1000 for (y = MIN_Y; y < MAX_Y; ++y)
1002 temp_pos = POS (x, y);
1003 if (get_point_board (temp_pos) == EMPTY)
1005 continue;
1008 draw_stone (temp_pos, get_point_board (temp_pos) == BLACK);
1013 static void
1014 draw_hoshi (unsigned short pos)
1016 /* color and drawmode are already set before this function (all lines
1017 and hoshi and stuff are drawn together) */
1019 if (!on_board(pos))
1021 return;
1024 if ((unsigned) I (pos) < MIN_X ||
1025 (unsigned) I (pos) >= MAX_X ||
1026 (unsigned) J (pos) < MIN_Y ||
1027 (unsigned) J (pos) >= MAX_Y)
1029 return;
1031 if (intersection_size > 8)
1033 rb->lcd_fillrect (pixel_x (pos) + LINE_OFFSET - 1,
1034 pixel_y (pos) + LINE_OFFSET - 1, 3, 3);
1036 else
1038 rb->lcd_drawpixel (pixel_x (pos) + LINE_OFFSET - 1,
1039 pixel_y (pos) + LINE_OFFSET - 1);
1040 rb->lcd_drawpixel (pixel_x (pos) + LINE_OFFSET + 1,
1041 pixel_y (pos) + LINE_OFFSET + 1);
1046 static void
1047 draw_all_hoshi (void)
1049 if (board_width != board_height)
1051 return;
1054 if (board_width == 19)
1056 draw_hoshi (POS (3, 3));
1057 draw_hoshi (POS (3, 9));
1058 draw_hoshi (POS (3, 15));
1060 draw_hoshi (POS (9, 3));
1061 draw_hoshi (POS (9, 9));
1062 draw_hoshi (POS (9, 15));
1064 draw_hoshi (POS (15, 3));
1065 draw_hoshi (POS (15, 9));
1066 draw_hoshi (POS (15, 15));
1068 else if (board_width == 9)
1070 draw_hoshi (POS (2, 2));
1071 draw_hoshi (POS (2, 6));
1073 draw_hoshi (POS (4, 4));
1075 draw_hoshi (POS (6, 2));
1076 draw_hoshi (POS (6, 6));
1078 else if (board_width == 13)
1080 draw_hoshi (POS (3, 3));
1081 draw_hoshi (POS (3, 9));
1083 draw_hoshi (POS (6, 6));
1085 draw_hoshi (POS (9, 3));
1086 draw_hoshi (POS (9, 9));