#include <stdio.h>
+#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <syscall.h>
#include <assert.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
#include <linux/input.h>
#include <libtwin/twin.h>
#include <libtwin/twin_linux_mouse.h>
#include <libtwin/twin_png.h>
+#include <libtwin/twin_jpeg.h>
#include "petitboot.h"
#include "petitboot-paths.h"
static twin_screen_t *pboot_screen;
-#define PBOOT_LEFT_PANE_SIZE 200
+#define PBOOT_INITIAL_MESSAGE \
+ "keys: 0=safe 1=720p 2=1080i 3=1080p del=GameOS"
+
+#define PBOOT_LEFT_PANE_SIZE 160
#define PBOOT_LEFT_PANE_COLOR 0x80000000
#define PBOOT_LEFT_LINE_COLOR 0xff000000
#define PBOOT_LEFT_FOCUS_WIDTH 80
#define PBOOT_LEFT_FOCUS_HEIGHT 80
-#define PBOOT_LEFT_FOCUS_XOFF 60
-#define PBOOT_LEFT_FOCUS_YOFF 60
+#define PBOOT_LEFT_FOCUS_XOFF 40
+#define PBOOT_LEFT_FOCUS_YOFF 40
#define PBOOT_LEFT_FOCUS_XRAD (6 * TWIN_FIXED_ONE)
#define PBOOT_LEFT_FOCUS_YRAD (6 * TWIN_FIXED_ONE)
#define PBOOT_LEFT_ICON_WIDTH 64
#define PBOOT_LEFT_ICON_HEIGHT 64
-#define PBOOT_LEFT_ICON_XOFF 70
-#define PBOOT_LEFT_ICON_YOFF 70
+#define PBOOT_LEFT_ICON_XOFF 50
+#define PBOOT_LEFT_ICON_YOFF 50
#define PBOOT_LEFT_ICON_STRIDE 100
#define PBOOT_RIGHT_OPTION_LMARGIN 30
#define PBOOT_RIGHT_SUBTITLE_TEXT_SIZE (18 * TWIN_FIXED_ONE)
#define PBOOT_RIGHT_TITLE_XOFFSET 80
#define PBOOT_RIGHT_TITLE_YOFFSET 30
-#define PBOOT_RIGHT_SUBTITLE_XOFFSET 200
+#define PBOOT_RIGHT_SUBTITLE_XOFFSET 100
#define PBOOT_RIGHT_SUBTITLE_YOFFSET 50
#define PBOOT_RIGHT_BADGE_XOFFSET 2
#define PBOOT_RIGHT_BADGE_YOFFSET 0
#define PBOOT_FOCUS_COLOR 0x10404040
+#define PBOOT_STATUS_PANE_COLOR 0x60606060
+#define PBOOT_STATUS_PANE_HEIGHT 20
+#define PBOOT_STATUS_PANE_XYMARGIN 20
+#define PBOOT_STATUS_TEXT_MARGIN 10
+#define PBOOT_STATUS_TEXT_SIZE (16 * TWIN_FIXED_ONE)
+#define PBOOT_STATUS_TEXT_COLOR 0xff000000
typedef struct _pboot_option pboot_option_t;
typedef struct _pboot_device pboot_device_t;
int mouse_target;
} pboot_rpane_t;
+typedef struct _pboot_spane {
+ twin_window_t *window;
+ char *text;
+} pboot_spane_t;
+
static pboot_lpane_t *pboot_lpane;
static pboot_rpane_t *pboot_rpane;
+static pboot_spane_t *pboot_spane;
+
+static int pboot_vmode_change = -1;
/* XXX move to twin */
static inline twin_bool_t twin_rect_intersect(twin_rect_t r1,
static twin_time_t pboot_rfocus_timeout (twin_time_t now, void *closure)
{
int dir = 1, dist, pos;
- const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 2, 3, 4, 5 };
+ const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 1, 2, 2, 3 };
dist = abs(pboot_rpane->focus_target - pboot_rpane->focus_start);
dir = dist > 5 ? 5 : dist;
}
-static void pboot_set_device_select(int sel)
+static void pboot_set_device_select(int sel, int force)
{
LOG("%s: %d -> %d\n", __FUNCTION__, pboot_dev_sel, sel);
- if (sel == pboot_dev_sel || sel >= pboot_dev_count)
+ if (!force && sel == pboot_dev_sel)
+ return;
+ if (sel >= pboot_dev_count)
return;
pboot_dev_sel = sel;
+ if (force) {
+ pboot_lpane->focus_curindex = sel;
+ if (sel < 0)
+ pboot_lpane->focus_target = 0 - PBOOT_LEFT_FOCUS_HEIGHT;
+ else
+ pboot_lpane->focus_target = PBOOT_LEFT_FOCUS_YOFF +
+ PBOOT_LEFT_ICON_STRIDE * sel;
+ pboot_rpane->focus_box.bottom = pboot_lpane->focus_target;
+ pboot_rpane->focus_box.bottom = pboot_rpane->focus_box.top +
+ PBOOT_RIGHT_FOCUS_HEIGHT;
+ twin_window_damage(pboot_lpane->window,
+ 0, 0,
+ pboot_lpane->window->pixmap->width,
+ pboot_lpane->window->pixmap->height);
+ twin_window_queue_paint(pboot_lpane->window);
+ }
pboot_rpane->focus_curindex = -1;
pboot_rpane->mouse_target = -1;
pboot_rpane->focus_box.top = -2*PBOOT_RIGHT_FOCUS_HEIGHT;
twin_window_queue_paint(pboot_rpane->window);
}
+static void pboot_create_rpane(void)
+{
+ pboot_rpane = calloc(1, sizeof(pboot_rpane_t));
+ assert(pboot_rpane);
+
+ pboot_rpane->window = twin_window_create(pboot_screen, TWIN_ARGB32,
+ TwinWindowPlain,
+ PBOOT_LEFT_PANE_SIZE, 0,
+ pboot_screen->width -
+ PBOOT_LEFT_PANE_SIZE,
+ pboot_screen->height);
+ assert(pboot_rpane->window);
+
+ pboot_rpane->window->draw = pboot_rpane_draw;
+ pboot_rpane->window->event = pboot_rpane_event;
+ pboot_rpane->window->client_data = pboot_rpane;
+
+ pboot_rpane->focus_curindex = -1;
+ pboot_rpane->focus_box.left = PBOOT_RIGHT_FOCUS_XOFF;
+ pboot_rpane->focus_box.top = -2*PBOOT_RIGHT_FOCUS_HEIGHT;
+ pboot_rpane->focus_box.right = pboot_rpane->window->pixmap->width -
+ 2 * PBOOT_RIGHT_FOCUS_XOFF;
+ pboot_rpane->focus_box.bottom = pboot_rpane->focus_box.top +
+ PBOOT_RIGHT_FOCUS_HEIGHT;
+ pboot_rpane->mouse_target = -1;
+ twin_window_show(pboot_rpane->window);
+ twin_window_queue_paint(pboot_rpane->window);
+}
+
+
static twin_time_t pboot_lfocus_timeout (twin_time_t now, void *closure)
{
int dir = 1, dist, pos;
- const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 2, 3, 4, 5 };
+ const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 1, 2, 2, 3 };
dist = abs(pboot_lpane->focus_target - pboot_lpane->focus_start);
+ dir = dist > 2 ? 2 : dist;
pos = pboot_lpane->focus_target - (int)pboot_lpane->focus_box.top;
if (pos == 0) {
- pboot_set_device_select(pboot_lpane->focus_curindex);
+ pboot_set_device_select(pboot_lpane->focus_curindex, 0);
return -1;
}
if (pos < 0) {
return TWIN_FALSE;
}
+static void pboot_quit(void)
+{
+ kill(0, SIGINT);
+}
+
twin_bool_t pboot_event_filter(twin_screen_t *screen,
twin_event_t *event)
{
pboot_cursor_hy);
break;
case TwinEventKeyDown:
+ switch(event->u.key.key) {
+ /* Gross hack for video modes, need something better ! */
+ case KEY_0:
+ pboot_vmode_change = 0; /* auto */
+ pboot_quit();
+ return TWIN_TRUE;
+ case KEY_1:
+ pboot_vmode_change = 3; /* 720p */
+ pboot_quit();
+ return TWIN_TRUE;
+ case KEY_2:
+ pboot_vmode_change = 4; /* 1080i */
+ pboot_quit();
+ return TWIN_TRUE;
+ case KEY_3:
+ pboot_vmode_change = 5; /* 1080p */
+ pboot_quit();
+ return TWIN_TRUE;
+
+ /* Another gross hack for booting back to gameos */
+ case KEY_BACKSPACE:
+ case KEY_DELETE:
+ system("boot-game-os");
+ pboot_quit();
+ }
case TwinEventKeyUp:
twin_screen_set_cursor(pboot_screen, NULL, 0, 0);
break;
twin_path_destroy(path);
}
-static void pboot_create_panels(void)
+static void pboot_create_lpane(void)
{
- /* left pane */
pboot_lpane = calloc(1, sizeof(pboot_lpane_t));
assert(pboot_lpane);
PBOOT_LEFT_FOCUS_HEIGHT;
pboot_lpane->mouse_target = -1;
twin_window_show(pboot_lpane->window);
+ twin_window_queue_paint(pboot_lpane->window);
+}
- /* right pane */
- pboot_rpane = calloc(1, sizeof(pboot_rpane_t));
- assert(pboot_rpane);
+static void pboot_spane_draw(twin_window_t *window)
+{
+ twin_pixmap_t *px = window->pixmap;
+ pboot_spane_t *spane = window->client_data;
+ twin_path_t *path;
+ twin_fixed_t tx, ty;
- pboot_rpane->window = twin_window_create(pboot_screen, TWIN_ARGB32,
- TwinWindowPlain,
- PBOOT_LEFT_PANE_SIZE, 0,
- pboot_screen->width -
- PBOOT_LEFT_PANE_SIZE,
- pboot_screen->height);
- assert(pboot_rpane->window);
+ /* Fill background */
+ twin_fill(px, PBOOT_STATUS_PANE_COLOR, TWIN_SOURCE,
+ 0, 0, px->width, px->height);
- pboot_rpane->window->draw = pboot_rpane_draw;
- pboot_rpane->window->event = pboot_rpane_event;
- pboot_rpane->window->client_data = pboot_rpane;
+ path = twin_path_create();
+ assert(path);
- pboot_rpane->focus_curindex = -1;
- pboot_rpane->focus_box.left = PBOOT_RIGHT_FOCUS_XOFF;
- pboot_rpane->focus_box.top = -2*PBOOT_RIGHT_FOCUS_HEIGHT;
- pboot_rpane->focus_box.right = pboot_rpane->window->pixmap->width -
- 2 * PBOOT_RIGHT_FOCUS_XOFF;
- pboot_rpane->focus_box.bottom = pboot_rpane->focus_box.top +
- PBOOT_RIGHT_FOCUS_HEIGHT;
- pboot_rpane->mouse_target = -1;
- twin_window_show(pboot_rpane->window);
+ twin_path_set_font_size(path, PBOOT_STATUS_TEXT_SIZE);
+ twin_path_set_font_style(path, TWIN_TEXT_UNHINTED);
+ tx = twin_int_to_fixed(PBOOT_STATUS_TEXT_MARGIN);
+ ty = twin_int_to_fixed(PBOOT_STATUS_PANE_HEIGHT - 2);
+ twin_path_move (path, tx, ty);
+ twin_path_utf8 (path, spane->text);
+ twin_paint_path (px, PBOOT_STATUS_TEXT_COLOR, path);
+
+ twin_path_destroy(path);
+}
+
+void pboot_message(const char *message)
+{
+ if (pboot_spane->text)
+ free(pboot_spane->text);
+ pboot_spane->text = strdup(message);
+ twin_window_damage(pboot_spane->window,
+ 0, 0,
+ pboot_spane->window->pixmap->width,
+ pboot_spane->window->pixmap->height);
+ twin_window_queue_paint(pboot_spane->window);
+}
+
+static void pboot_create_spane(void)
+{
+ pboot_spane = calloc(1, sizeof(pboot_spane_t));
+ assert(pboot_spane);
+
+ pboot_spane->window = twin_window_create(pboot_screen, TWIN_ARGB32,
+ TwinWindowPlain,
+ PBOOT_LEFT_PANE_SIZE +
+ PBOOT_STATUS_PANE_XYMARGIN,
+ pboot_screen->height -
+ PBOOT_STATUS_PANE_HEIGHT,
+ pboot_screen->width -
+ PBOOT_LEFT_PANE_SIZE -
+ 2*PBOOT_STATUS_PANE_XYMARGIN,
+ PBOOT_STATUS_PANE_HEIGHT);
+ assert(pboot_spane->window);
+
+ pboot_spane->window->draw = pboot_spane_draw;
+ pboot_spane->window->client_data = pboot_spane;
+ pboot_spane->text = strdup(PBOOT_INITIAL_MESSAGE);
+ twin_window_show(pboot_spane->window);
+ twin_window_queue_paint(pboot_spane->window);
}
int pboot_add_device(const char *dev_id, const char *name,
int pboot_remove_device(const char *dev_id)
{
- int i, new_dev_index;
pboot_device_t *dev = NULL;
+ int i, newsel = pboot_dev_sel;
/* find the matching device */
for (i = 0; i < pboot_dev_count; i++) {
if (!dev)
return TWIN_FALSE;
- /* select the newly-focussed device */
- if (i == pboot_dev_count - 1)
- new_dev_index = i - 1;
- else
- new_dev_index = i + 1;
-
memmove(pboot_devices + i, pboot_devices + i + 1,
sizeof(*pboot_devices) * (pboot_dev_count + i - 1));
-
pboot_devices[--pboot_dev_count] = NULL;
- pboot_set_device_select(new_dev_index);
- twin_window_damage(pboot_lpane->window,
- dev->box.left, dev->box.top,
- dev->box.right, dev->box.bottom);
- twin_window_queue_paint(pboot_lpane->window);
+ /* select the newly-focussed device */
+ if (pboot_dev_sel > i)
+ newsel = pboot_dev_sel - 1;
+ else if (pboot_dev_sel == i && i >= pboot_dev_count)
+ newsel = pboot_dev_count - 1;
+ pboot_set_device_select(newsel, 1);
/* todo: free device & options */
return TWIN_TRUE;
}
+static void pboot_make_background(void)
+{
+ twin_pixmap_t *filepic, *scaledpic;
+ const char *background_path;
+
+ /* Set background pixmap */
+ LOG("loading background...");
+ background_path = artwork_pathname("background.jpg");
+ filepic = twin_jpeg_to_pixmap(background_path, TWIN_ARGB32);
+ LOG("%s\n", filepic ? "ok" : "failed");
+
+ if (filepic == NULL)
+ return;
+
+ if (pboot_screen->height == filepic->height &&
+ pboot_screen->width == filepic->width)
+ scaledpic = filepic;
+ else {
+ twin_fixed_t sx, sy;
+ twin_operand_t srcop;
+
+ scaledpic = twin_pixmap_create(TWIN_ARGB32,
+ pboot_screen->width,
+ pboot_screen->height);
+ if (scaledpic == NULL) {
+ twin_pixmap_destroy(filepic);
+ return;
+ }
+ sx = twin_fixed_div(twin_int_to_fixed(filepic->width),
+ twin_int_to_fixed(pboot_screen->width));
+ sy = twin_fixed_div(twin_int_to_fixed(filepic->height),
+ twin_int_to_fixed(pboot_screen->height));
+
+ twin_matrix_scale(&filepic->transform, sx, sy);
+ srcop.source_kind = TWIN_PIXMAP;
+ srcop.u.pixmap = filepic;
+ twin_composite(scaledpic, 0, 0, &srcop, 0, 0,
+ NULL, 0, 0, TWIN_SOURCE,
+ pboot_screen->width, pboot_screen->height);
+ twin_pixmap_destroy(filepic);
+
+ }
+ twin_screen_set_background(pboot_screen, scaledpic);
+}
+
+#define PS3FB_IOCTL_SETMODE _IOW('r', 1, int)
+#define PS3FB_IOCTL_GETMODE _IOR('r', 2, int)
+
static void exitfunc(void)
{
#ifndef _USE_X11
if (pboot_fbdev)
twin_fbdev_destroy(pboot_fbdev);
pboot_fbdev = NULL;
+ if (pboot_vmode_change != -1) {
+ int fd = open("/dev/fb0", O_RDWR);
+ if (fd >= 0)
+ ioctl(fd, PS3FB_IOCTL_SETMODE,
+ (unsigned long)&pboot_vmode_change);
+ close(fd);
+ }
#endif
}
syscall(__NR_exit);
}
+static void usage(const char *progname)
+{
+ fprintf(stderr, "Usage: %s [-u] [-h]\n", progname);
+}
+
int main(int argc, char **argv)
{
- twin_pixmap_t *pic;
- const char *background_path;
+ int c;
+ int udev_trigger = 0;
+
+ for (;;) {
+ c = getopt(argc, argv, "u::h");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'u':
+ udev_trigger = 1;
+ break;
+ case 'h':
+ usage(argv[0]);
+ return EXIT_SUCCESS;
+ default:
+ fprintf(stderr, "Unknown option '%c'\n", c);
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
atexit(exitfunc);
signal(SIGINT, sigint);
twin_linux_mouse_create(NULL, pboot_screen);
if (pboot_fbdev != NULL) {
- char *cursor_path = artwork_pathname("cursor");
+ char *cursor_path = artwork_pathname("cursor.gz");
pboot_cursor = twin_load_X_cursor(cursor_path, 2,
&pboot_cursor_hx,
&pboot_cursor_hy);
#endif
/* Set background pixmap */
- background_path = artwork_pathname("background.png");
- LOG("loading background: %s...", background_path);
- pic = twin_png_to_pixmap(background_path, TWIN_ARGB32);
- LOG("%s\n", pic ? "ok" : "failed");
- if (pic)
- twin_screen_set_background(pboot_screen, pic);
+ pboot_make_background();
/* Init more stuffs */
- pboot_create_panels();
- twin_window_queue_paint(pboot_lpane->window);
- twin_window_queue_paint(pboot_rpane->window);
+ pboot_create_lpane();
+ pboot_create_rpane();
+ pboot_create_spane();
- if (!pboot_start_device_discovery()) {
+ if (!pboot_start_device_discovery(udev_trigger)) {
LOG("Couldn't start device discovery!\n");
return 1;
}