+static uint16_t *find_valid_point(struct cwiid_state *state)
+{
+ unsigned int i;
+
+ for (i = 0; i < CWIID_IR_SRC_COUNT; i++) {
+ if (state->ir_src[i].valid)
+ return state->ir_src[i].pos;
+ }
+ return NULL;
+}
+
+static void calibrate(SDL_Surface *screen,
+ cwiid_wiimote_t *wiimote,
+ struct coord *calib, unsigned x, unsigned y)
+{
+ uint16_t *pos;
+ struct cwiid_state state;
+ unsigned int last_x = MAX_X, last_y = MAX_Y, count = 0;
+
+ /* Must see it for a full half second. */
+ while (count < 20) {
+ SDL_Event event;
+
+ if (cwiid_get_state(wiimote, &state))
+ errx(1, "No wii state");
+
+ pos = find_valid_point(&state);
+ if (!pos || pos[0] != last_x || pos[1] != last_y)
+ count = 0;
+
+ if (pos) {
+ last_x = pos[0];
+ last_y = pos[1];
+ count++;
+ }
+
+ SDL_Delay(25);
+ if (SDL_PollEvent(&event)
+ && (event.type == SDL_QUIT
+ || (event.type == SDL_KEYDOWN
+ && event.key.keysym.sym == SDLK_ESCAPE))) {
+ SDL_Quit();
+ exit(0);
+ }
+ }
+
+ calib->x = last_x;
+ calib->y = last_y;
+ printf("Calibration point: %u,%u\n", last_x, last_y);
+}
+
+static bool map_coord(unsigned int x, unsigned int y,
+ const struct coord calib[],
+ struct coord *res)
+{
+ struct coord line_start, line_end;
+ struct coord pos = { x, y }, intersect;
+ double d1, d2;
+
+ /* Calibration layout:
+ *
+ * 0 1
+ *
+ * 3 2
+ *
+ * We figure out the distance to each side, and then map using:
+ *
+ * x = d1 / (d1 + d2) * (rawend - rawstart) + rawstart
+ */
+ line_start.x = 0;
+ line_end.x = MAX_X-1;
+ line_start.y = line_end.y = y;
+
+ if (!lines_intersect(&calib[0], &calib[3], &line_start, &line_end,
+ &intersect))
+ return false;
+ d1 = dist(&pos, &intersect);
+ if (!lines_intersect(&calib[1], &calib[2], &line_start, &line_end,
+ &intersect))
+ return false;
+ d2 = dist(&pos, &intersect);
+ res->x = d1 / (d1 + d2) * MAX_X;
+
+ line_start.y = 0;
+ line_end.y = MAX_Y-1;
+ line_start.x = line_end.x = x;
+
+ if (!lines_intersect(&calib[0], &calib[1], &line_start, &line_end,
+ &intersect))
+ return false;
+ d1 = dist(&pos, &intersect);
+ if (!lines_intersect(&calib[3], &calib[2], &line_start, &line_end,
+ &intersect))
+ return false;
+ d2 = dist(&pos, &intersect);
+ res->y = d1 / (d1 + d2) * MAX_Y;
+
+ return true;
+}
+
+static struct line_segment *new_line(unsigned int startx, unsigned int starty,
+ unsigned int endx, unsigned int endy,
+ const struct coord calib[])
+{
+ struct line_segment *l = malloc(sizeof(*l));
+
+ l->ignore = false;
+ if (!map_coord(startx, starty, calib, &l->start)
+ || !map_coord(endx, endy, calib, &l->end)) {
+ free(l);
+ return NULL;
+ }
+ return l;
+}
+
+