+static void make_cross(unsigned x, unsigned y,
+ struct line_segment *seg1,
+ struct line_segment *seg2)
+{
+ seg1->start.x = x-5;
+ seg1->start.y = y-5;
+ seg1->end.x = x+5;
+ seg1->end.y = y+5;
+ seg2->start.x = x-5;
+ seg2->start.y = y+5;
+ seg2->end.x = x+5;
+ seg2->end.y = y-5;
+}
+
+static void calibrate(SDL_Surface *screen,
+ cwiid_wiimote_t *wiimote,
+ struct coord *calib, unsigned x, unsigned y)
+{
+ struct line_segment seg1, seg2;
+ struct cwiid_state state;
+ unsigned int i;
+
+ make_cross(x, y, &seg1, &seg2);
+ thick_line(screen, &seg1, 0);
+ thick_line(screen, &seg2, 0);
+
+ do {
+ SDL_Event event;
+ if (cwiid_get_state(wiimote, &state))
+ errx(1, "No wii state");
+
+ for (i = 0; i < CWIID_IR_SRC_COUNT; i++) {
+ if (state.ir_src[i].valid)
+ break;
+ }
+ 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);
+ }
+ } while (i == CWIID_IR_SRC_COUNT);
+
+ thick_line(screen, &seg1, 0xFFFFFFFF);
+ thick_line(screen, &seg2, 0xFFFFFFFF);
+
+ calib->x = state.ir_src[i].pos[0];
+ calib->y = state.ir_src[i].pos[1];
+ printf("Calibration point: %u,%u\n",
+ state.ir_src[i].pos[0],
+ state.ir_src[i].pos[1]);
+ make_cross(calib->x, calib->y, &seg1, &seg2);
+
+ thick_line(screen, &seg1, 0xFFFF0000);
+ thick_line(screen, &seg2, 0xFFFF0000);
+}
+
+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 - 2*CALIB_OFF) + CALIB_OFF;
+
+ 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;
+}
+
+