initial pandora port, with hardware scaling and stuff
authornotaz <notaz@pixelinis>
Sun, 4 Sep 2011 17:02:19 +0000 (20:02 +0300)
committernotaz <notaz@pixelinis>
Mon, 5 Sep 2011 21:18:01 +0000 (00:18 +0300)
16 files changed:
.gitignore
common.h
gp2x/gp2x.c
gp2x/gp2x.h
gui.c
input.c
main.c
pandora/Makefile [new file with mode: 0644]
pandora/linux/fbdev.c [new file with mode: 0644]
pandora/linux/fbdev.h [new file with mode: 0644]
pandora/linux/omapfb.h [new file with mode: 0644]
pandora/linux/xenv.c [new file with mode: 0644]
pandora/linux/xenv.h [new file with mode: 0644]
pandora/pnd.c [new file with mode: 0644]
pandora/pnd.h [new file with mode: 0644]
video.c

index 6298ed1..bf5c80b 100644 (file)
@@ -2,3 +2,6 @@
 *.u
 *.z
 gpsp.gpe
 *.u
 *.z
 gpsp.gpe
+tags
+cscope.out
+pandora/linux
index f43d75c..7eea8b6 100644 (file)
--- a/common.h
+++ b/common.h
@@ -251,4 +251,8 @@ typedef u32 fixed16_16;
 //  #define STDIO_DEBUG
 #endif
 
 //  #define STDIO_DEBUG
 #endif
 
+#ifdef PND_BUILD
+  #include "pandora/pnd.h"
+#endif
+
 #endif
 #endif
index 8bad610..ad3c215 100644 (file)
@@ -39,7 +39,7 @@ static u32 gp2x_audio_volume = 74/2;
 static volatile u16 *gpsp_gp2x_memregs;
 static volatile u32 *gpsp_gp2x_memregl;
 
 static volatile u16 *gpsp_gp2x_memregs;
 static volatile u32 *gpsp_gp2x_memregl;
 
-u32 button_plat_mask_to_config[] =
+u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT] =
 {
   GP2X_UP,
   GP2X_LEFT,
 {
   GP2X_UP,
   GP2X_LEFT,
@@ -59,7 +59,7 @@ u32 button_plat_mask_to_config[] =
   GP2X_VOL_MIDDLE
 };
 
   GP2X_VOL_MIDDLE
 };
 
-u32 gamepad_config_map[16] =
+u32 gamepad_config_map[PLAT_BUTTON_COUNT] =
 {
   BUTTON_ID_UP,                 // Up
   BUTTON_ID_LEFT,               // Left
 {
   BUTTON_ID_UP,                 // Up
   BUTTON_ID_LEFT,               // Left
index 9218704..97b8d3c 100644 (file)
@@ -33,7 +33,8 @@ void gpsp_plat_quit(void);
 u32 gpsp_plat_joystick_read(void);
 u32 gpsp_plat_buttons_to_cursor(u32 buttons);
 
 u32 gpsp_plat_joystick_read(void);
 u32 gpsp_plat_buttons_to_cursor(u32 buttons);
 
-extern u32 button_plat_mask_to_config[];
+#define PLAT_BUTTON_COUNT 16
+extern u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT];
 
 void gp2x_sound_volume(u32 volume_up);
 void gp2x_quit();
 
 void gp2x_sound_volume(u32 volume_up);
 void gp2x_quit();
diff --git a/gui.c b/gui.c
index 0184a18..22a39e0 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -569,11 +569,11 @@ struct _menu_option_type
   void (* action_function)();
   void (* passive_function)();
   struct _menu_type *sub_menu;
   void (* action_function)();
   void (* passive_function)();
   struct _menu_type *sub_menu;
-  char *display_string;
+  const char *display_string;
   void *options;
   u32 *current_option;
   u32 num_options;
   void *options;
   u32 *current_option;
   u32 num_options;
-  char *help_string;
+  const char *help_string;
   u32 line_number;
   menu_option_type_enum option_type;
 };
   u32 line_number;
   menu_option_type_enum option_type;
 };
@@ -740,16 +740,26 @@ u32 gamepad_config_line_to_button[] =
 
 #endif
 
 
 #endif
 
+#ifdef PND_BUILD
+
+u32 gamepad_config_line_to_button[] =
+ { 0, 2, 1, 3, 8, 9, 10, 11, 6, 7, 4, 5, 12, 13, 14, 15 };
+
+#endif
+
 u8 *scale_options[] =
 {
 u8 *scale_options[] =
 {
-#ifdef WIZ_BUILD
+#ifdef PSP_BUILD
+  "unscaled 3:2", "scaled 3:2", "fullscreen 16:9"
+#elif defined(WIZ_BUILD)
   "unscaled 3:2", "scaled 3:2 (slower)",
   "unscaled 3:2 (anti-tear)", "scaled 3:2 (anti-tear)"
   "unscaled 3:2", "scaled 3:2 (slower)",
   "unscaled 3:2 (anti-tear)", "scaled 3:2 (anti-tear)"
-#else
+#elif defined(PND_BUILD)
+  "unscaled", "2x", "3x", "fullscreen"
+#elif defined(GP2X_BUILD)
   "unscaled 3:2", "scaled 3:2", "fullscreen", "scaled 3:2 (software)"
   "unscaled 3:2", "scaled 3:2", "fullscreen", "scaled 3:2 (software)"
-#ifdef PSP_BUILD
-  " 16:9"
-#endif
+#else
+  "unscaled 3:2"
 #endif
 };
 
 #endif
 };
 
@@ -1024,7 +1034,7 @@ void get_savestate_snapshot(u8 *savestate_filename)
   else
   {
     memset(snapshot_buffer, 0, 240 * 160 * 2);
   else
   {
     memset(snapshot_buffer, 0, 240 * 160 * 2);
-    print_string_ext("No savestate exists for this slot.",
+    print_string_ext("No savestate in this slot.",
      0xFFFF, 0x0000, 15, 75, snapshot_buffer, 240, 0, 0, FONT_HEIGHT);
     print_string("---------- --/--/---- --:--:--          ", COLOR_HELP_TEXT,
      COLOR_BG, 10, 40);
      0xFFFF, 0x0000, 15, 75, snapshot_buffer, 240, 0, 0, FONT_HEIGHT);
     print_string("---------- --/--/---- --:--:--          ", COLOR_HELP_TEXT,
      COLOR_BG, 10, 40);
@@ -1084,7 +1094,7 @@ u32 menu(u16 *original_screen)
   auto void choose_menu();
   auto void clear_help();
 
   auto void choose_menu();
   auto void clear_help();
 
-  u8 *gamepad_help[] =
+  static const u8 * const gamepad_help[] =
   {
     "Up button on GBA d-pad.",
     "Down button on GBA d-pad.",
   {
     "Up button on GBA d-pad.",
     "Down button on GBA d-pad.",
@@ -1315,16 +1325,19 @@ u32 menu(u16 *original_screen)
      (u32 *)(&screen_scale),
      sizeof(scale_options) / sizeof(scale_options[0]),
 #ifndef GP2X_BUILD
      (u32 *)(&screen_scale),
      sizeof(scale_options) / sizeof(scale_options[0]),
 #ifndef GP2X_BUILD
-     "Determines how the GBA screen is resized in relation to the entire\n"
-     "screen. Select unscaled 3:2 for GBA resolution, scaled 3:2 for GBA\n"
+     "Determines how the GBA screen is resized in relation to the\n"
+     "entire screen."
+#ifdef PSP_BUILD
+     " Select unscaled 3:2 for GBA resolution, scaled 3:2 for GBA\n"
      "aspect ratio scaled to fill the height of the PSP screen, and\n"
      "fullscreen to fill the entire PSP screen."
      "aspect ratio scaled to fill the height of the PSP screen, and\n"
      "fullscreen to fill the entire PSP screen."
+#endif
 #endif
      "", 2),
 #ifndef GP2X_BUILD
     string_selection_option(NULL, "Screen filtering", yes_no_options,
      (u32 *)(&screen_filter), 2,
 #endif
      "", 2),
 #ifndef GP2X_BUILD
     string_selection_option(NULL, "Screen filtering", yes_no_options,
      (u32 *)(&screen_filter), 2,
-     "Determines whether or not bilinear filtering should be used when\n"
+     "Determines whether or not filtering should be used when\n"
      "scaling the screen. Selecting this will produce a more even and\n"
      "smooth image, at the cost of being blurry and having less vibrant\n"
      "colors.", 3),
      "scaling the screen. Selecting this will produce a more even and\n"
      "smooth image, at the cost of being blurry and having less vibrant\n"
      "colors.", 3),
@@ -1352,8 +1365,8 @@ u32 menu(u16 *original_screen)
 #ifndef GP2X_BUILD
      "If objects in the game flicker at a regular rate certain manual\n"
      "frameskip values may cause them to normally disappear. Change this\n"
 #ifndef GP2X_BUILD
      "If objects in the game flicker at a regular rate certain manual\n"
      "frameskip values may cause them to normally disappear. Change this\n"
-     "value to 'random' to avoid this. Do not use otherwise, as it tends to\n"
-     "make the image quality worse, especially in high motion games."
+     "value to 'random' to avoid this. Do not use otherwise, as it tends\n"
+     "to make the image quality worse, especially in high motion games."
 #endif
      "", 7),
     string_selection_option(NULL, "Audio output", yes_no_options,
 #endif
      "", 7),
     string_selection_option(NULL, "Audio output", yes_no_options,
@@ -1395,25 +1408,29 @@ u32 menu(u16 *original_screen)
     cheat_option(7),
     cheat_option(8),
     cheat_option(9),
     cheat_option(7),
     cheat_option(8),
     cheat_option(9),
+#if defined(PSP_BUILD) || defined(GP2X_BUILD)
     string_selection_option(NULL, "Clock speed",
      clock_speed_options, &clock_speed_number,
      sizeof(clock_speed_options) / sizeof(clock_speed_options[0]),
      "Change the clock speed of the device. Higher clock\n"
      "speed will yield better performance, but will drain\n"
      "battery life further.", 11),
     string_selection_option(NULL, "Clock speed",
      clock_speed_options, &clock_speed_number,
      sizeof(clock_speed_options) / sizeof(clock_speed_options[0]),
      "Change the clock speed of the device. Higher clock\n"
      "speed will yield better performance, but will drain\n"
      "battery life further.", 11),
+#endif
     string_selection_option(NULL, "Update backup",
      update_backup_options, &update_backup_flag, 2,
 #ifdef GP2X_BUILD
      "Determines when in-game save files should be\n"
     string_selection_option(NULL, "Update backup",
      update_backup_options, &update_backup_flag, 2,
 #ifdef GP2X_BUILD
      "Determines when in-game save files should be\n"
-     "written back to SD card.",
+     "written back to SD card."
 #else
      "Determines when in-game save files should be written back to\n"
 #else
      "Determines when in-game save files should be written back to\n"
-     "memstick. If set to 'automatic' writebacks will occur shortly after\n"
-     "the game's backup is altered. On 'exit only' it will only be written\n"
-     "back when you exit from this menu (NOT from using the home button).\n"
-     "Use the latter with extreme care.",
+     "card. If set to 'automatic' writebacks will occur shortly after\n"
+     "the game's backup is altered. On 'exit only' it will only be\n"
+     "written back when you exit from this menu.\n"
+#ifdef PSP
+     "(NOT from using the home button), use the latter with extreme care."
+#endif
 #endif
 #endif
-     12),
+     "", 12),
     submenu_option(NULL, "Back", "Return to the main menu.", 14)
   };
 
     submenu_option(NULL, "Back", "Return to the main menu.", 14)
   };
 
@@ -1483,7 +1500,7 @@ u32 menu(u16 *original_screen)
 
 #endif
 
 
 #endif
 
-#ifdef GP2X_BUILD
+#if defined(GP2X_BUILD) || defined(PND_BUILD)
 
   menu_option_type gamepad_config_options[] =
   {
 
   menu_option_type gamepad_config_options[] =
   {
@@ -1503,10 +1520,18 @@ u32 menu(u16 *original_screen)
     gamepad_config_option("Start        ", 10),
 #endif
     gamepad_config_option("Select       ", 11),
     gamepad_config_option("Start        ", 10),
 #endif
     gamepad_config_option("Select       ", 11),
-#ifndef WIZ_BUILD
+#if !defined(WIZ_BUILD) && !defined(PND_BUILD)
     gamepad_config_option("Stick Push   ", 12),
 #endif
     gamepad_config_option("Stick Push   ", 12),
 #endif
+#ifdef PND_BUILD
+    gamepad_config_option("1            ", 12),
+    gamepad_config_option("2            ", 13),
+    gamepad_config_option("3            ", 14),
+    gamepad_config_option("4            ", 15),
+    submenu_option(NULL, "Back", "Return to the main menu.", 16)
+#else
     submenu_option(NULL, "Back", "Return to the main menu.", 14)
     submenu_option(NULL, "Back", "Return to the main menu.", 14)
+#endif
   };
 
 
   };
 
 
@@ -1665,13 +1690,13 @@ u32 menu(u16 *original_screen)
 
       if(display_option == current_option)
       {
 
       if(display_option == current_option)
       {
-        print_string_pad(line_buffer, COLOR_ACTIVE_ITEM, COLOR_BG, 10,
-         (display_option->line_number * 10) + 40, 41);
+        print_string_pad(line_buffer, COLOR_ACTIVE_ITEM, COLOR_BG, 6,
+         (display_option->line_number * 10) + 40, 36);
       }
       else
       {
       }
       else
       {
-        print_string_pad(line_buffer, COLOR_INACTIVE_ITEM, COLOR_BG, 10,
-         (display_option->line_number * 10) + 40, 41);
+        print_string_pad(line_buffer, COLOR_INACTIVE_ITEM, COLOR_BG, 6,
+         (display_option->line_number * 10) + 40, 36);
       }
     }
 
       }
     }
 
diff --git a/input.c b/input.c
index 4b908bb..acd01f5 100644 (file)
--- a/input.c
+++ b/input.c
@@ -454,7 +454,7 @@ u32 update_input()
   handled_buttons = (last_buttons ^ buttons) & buttons;
   last_buttons = buttons;
 
   handled_buttons = (last_buttons ^ buttons) & buttons;
   last_buttons = buttons;
 
-  for(i = 0; i < 16; i++)
+  for(i = 0; i < PLAT_BUTTON_COUNT; i++)
   {
     if(handled_buttons & button_plat_mask_to_config[i])
       button_id = gamepad_config_map[i];
   {
     if(handled_buttons & button_plat_mask_to_config[i])
       button_id = gamepad_config_map[i];
diff --git a/main.c b/main.c
index 0d88b37..ad79024 100644 (file)
--- a/main.c
+++ b/main.c
@@ -203,9 +203,6 @@ int main(int argc, char *argv[])
 #endif
 
   getcwd(main_path, 512);
 #endif
 
   getcwd(main_path, 512);
-  load_config_file();
-
-  gamepak_filename[0] = 0;
 
 #ifdef PSP_BUILD
   delay_us(2500000);
 
 #ifdef PSP_BUILD
   delay_us(2500000);
@@ -214,6 +211,9 @@ int main(int argc, char *argv[])
 #ifndef PC_BUILD
   gpsp_plat_init();
 #endif
 #ifndef PC_BUILD
   gpsp_plat_init();
 #endif
+  load_config_file();
+
+  gamepak_filename[0] = 0;
 
   init_video();
 
 
   init_video();
 
@@ -235,7 +235,11 @@ int main(int argc, char *argv[])
     debug_screen_printl("a860e8c0b6d573d191e4ec7db1b1e4f6                  ");
     debug_screen_printl("                                                  ");
     debug_screen_printl("When you do get it name it gba_bios.bin and put it");
     debug_screen_printl("a860e8c0b6d573d191e4ec7db1b1e4f6                  ");
     debug_screen_printl("                                                  ");
     debug_screen_printl("When you do get it name it gba_bios.bin and put it");
+#ifdef PND_BUILD
+    debug_screen_printl("in <CD card>/pandora/appdata/gpsp/ .              ");
+#else
     debug_screen_printl("in the same directory as gpSP.                    ");
     debug_screen_printl("in the same directory as gpSP.                    ");
+#endif
     debug_screen_printl("                                                  ");
     debug_screen_printl("Press any button to exit.                         ");
 
     debug_screen_printl("                                                  ");
     debug_screen_printl("Press any button to exit.                         ");
 
diff --git a/pandora/Makefile b/pandora/Makefile
new file mode 100644 (file)
index 0000000..090cccb
--- /dev/null
@@ -0,0 +1,41 @@
+# gpSP makefile
+# Gilead Kutnick - Exophase
+# pandora port - notaz
+
+# Global definitions
+
+CC        = $(CROSS_COMPILE)gcc
+
+OBJS      = pnd.o main.o cpu.o memory.o video.o input.o sound.o gui.o \
+            cheats.o zip.o cpu_threaded.o arm_stub.o video_blend.o warm.o \
+            linux/fbdev.o linux/xenv.o
+BIN       = gpsp
+
+# Platform specific definitions 
+
+VPATH      += .. ../arm
+CFLAGS     += -DARM_ARCH -DPND_BUILD
+CFLAGS     += -funsigned-char
+CFLAGS     += -mcpu=cortex-a8 -mtune=cortex-a8 -mfloat-abi=softfp -ffast-math
+CFLAGS     += -fno-common -fno-builtin
+CFLAGS     += -ggdb
+CFLAGS     += -O2
+
+# expecting to have PATH set up to get correct sdl-config first
+CFLAGS     += `sdl-config --cflags`
+LIBS       += `sdl-config --libs`
+LIBS       += -ldl -lpthread -lz
+
+# Compilation:
+
+%.o: %.S
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+all:   $(BIN)
+
+$(BIN): $(OBJS)
+       $(CC) $(OBJS) $(LIBS) -o $(BIN)
+
+clean:
+       rm -f *.o $(BIN) 
+
diff --git a/pandora/linux/fbdev.c b/pandora/linux/fbdev.c
new file mode 100644 (file)
index 0000000..9d532a5
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * (C) Gražvydas "notaz" Ignotas, 2009-2010
+ *
+ * This work is licensed under the terms of any of these licenses
+ * (at your option):
+ *  - GNU GPL, version 2 or later.
+ *  - GNU LGPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <linux/fb.h>
+#include <linux/matroxfb.h>
+
+#include "fbdev.h"
+
+struct vout_fbdev {
+       int     fd;
+       void    *mem;
+       size_t  mem_size;
+       struct  fb_var_screeninfo fbvar_old;
+       struct  fb_var_screeninfo fbvar_new;
+       int     buffer_write;
+       int     fb_size;
+       int     buffer_count;
+       int     top_border, bottom_border;
+};
+
+void *vout_fbdev_flip(struct vout_fbdev *fbdev)
+{
+       int draw_buf;
+
+       if (fbdev->buffer_count < 2)
+               return fbdev->mem;
+
+       draw_buf = fbdev->buffer_write;
+       fbdev->buffer_write++;
+       if (fbdev->buffer_write >= fbdev->buffer_count)
+               fbdev->buffer_write = 0;
+
+       fbdev->fbvar_new.yoffset = 
+               (fbdev->top_border + fbdev->fbvar_new.yres + fbdev->bottom_border) * draw_buf +
+               fbdev->top_border;
+
+       ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new);
+
+       return (char *)fbdev->mem + fbdev->fb_size * fbdev->buffer_write;
+}
+
+void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev)
+{
+       int arg = 0;
+       ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &arg);
+}
+
+/* it is recommended to call vout_fbdev_clear() before this */
+void *vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, int bpp,
+                     int left_border, int right_border, int top_border, int bottom_border, int buffer_cnt)
+{
+       int w_total = left_border + w + right_border;
+       int h_total = top_border + h + bottom_border;
+       size_t mem_size;
+       int ret;
+
+       // unblank to be sure the mode is really accepted
+       ioctl(fbdev->fd, FBIOBLANK, FB_BLANK_UNBLANK);
+
+       if (fbdev->fbvar_new.bits_per_pixel != bpp ||
+                       fbdev->fbvar_new.xres != w ||
+                       fbdev->fbvar_new.yres != h ||
+                       fbdev->fbvar_new.xres_virtual != w_total||
+                       fbdev->fbvar_new.yres_virtual < h_total ||
+                       fbdev->fbvar_new.xoffset != left_border ||
+                       fbdev->buffer_count != buffer_cnt)
+       {
+               if (fbdev->fbvar_new.bits_per_pixel != bpp ||
+                               w != fbdev->fbvar_new.xres || h != fbdev->fbvar_new.yres)
+                       printf(" switching to %dx%d@%d\n", w, h, bpp);
+
+               fbdev->fbvar_new.xres = w;
+               fbdev->fbvar_new.yres = h;
+               fbdev->fbvar_new.xres_virtual = w_total;
+               fbdev->fbvar_new.yres_virtual = h_total * buffer_cnt;
+               fbdev->fbvar_new.xoffset = left_border;
+               fbdev->fbvar_new.yoffset = top_border;
+               fbdev->fbvar_new.bits_per_pixel = bpp;
+               fbdev->fbvar_new.nonstd = 0; // can set YUV here on omapfb
+               fbdev->buffer_count = buffer_cnt;
+               fbdev->buffer_write = 1;
+
+               // seems to help a bit to avoid glitches
+               vout_fbdev_wait_vsync(fbdev);
+
+               ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new);
+               if (ret == -1) {
+                       // retry with no multibuffering
+                       fbdev->fbvar_new.yres_virtual = h_total;
+                       ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new);
+                       if (ret == -1) {
+                               perror("FBIOPUT_VSCREENINFO ioctl");
+                               return NULL;
+                       }
+                       fbdev->buffer_count = 1;
+                       fbdev->buffer_write = 0;
+                       fprintf(stderr, "Warning: failed to increase virtual resolution, "
+                                       "multibuffering disabled\n");
+               }
+
+       }
+
+       fbdev->fb_size = w_total * h_total * bpp / 8;
+       fbdev->top_border = top_border;
+       fbdev->bottom_border = bottom_border;
+
+       mem_size = fbdev->fb_size * fbdev->buffer_count;
+       if (fbdev->mem_size >= mem_size)
+               goto out;
+
+       if (fbdev->mem != NULL)
+               munmap(fbdev->mem, fbdev->mem_size);
+
+       fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0);
+       if (fbdev->mem == MAP_FAILED && fbdev->buffer_count > 1) {
+               fprintf(stderr, "Warning: can't map %zd bytes, doublebuffering disabled\n", mem_size);
+               fbdev->buffer_count = 1;
+               fbdev->buffer_write = 0;
+               mem_size = fbdev->fb_size;
+               fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0);
+       }
+       if (fbdev->mem == MAP_FAILED) {
+               fbdev->mem = NULL;
+               fbdev->mem_size = 0;
+               perror("mmap framebuffer");
+               return NULL;
+       }
+
+       fbdev->mem_size = mem_size;
+
+out:
+       return (char *)fbdev->mem + fbdev->fb_size * fbdev->buffer_write;
+}
+
+void vout_fbdev_clear(struct vout_fbdev *fbdev)
+{
+       memset(fbdev->mem, 0, fbdev->mem_size);
+}
+
+void vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count)
+{
+       int stride = fbdev->fbvar_new.xres_virtual * fbdev->fbvar_new.bits_per_pixel / 8;
+       int i;
+
+       if (y + count > fbdev->top_border + fbdev->fbvar_new.yres)
+               count = fbdev->top_border + fbdev->fbvar_new.yres - y;
+
+       if (y >= 0 && count > 0)
+               for (i = 0; i < fbdev->buffer_count; i++)
+                       memset((char *)fbdev->mem + fbdev->fb_size * i + y * stride, 0, stride * count);
+}
+
+int vout_fbdev_get_fd(struct vout_fbdev *fbdev)
+{
+       return fbdev->fd;
+}
+
+struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int bpp, int buffer_cnt)
+{
+       struct vout_fbdev *fbdev;
+       int req_w, req_h;
+       void *pret;
+       int ret;
+
+       fbdev = calloc(1, sizeof(*fbdev));
+       if (fbdev == NULL)
+               return NULL;
+
+       fbdev->fd = open(fbdev_name, O_RDWR);
+       if (fbdev->fd == -1) {
+               fprintf(stderr, "%s: ", fbdev_name);
+               perror("open");
+               goto fail_open;
+       }
+
+       ret = ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->fbvar_old);
+       if (ret == -1) {
+               perror("FBIOGET_VSCREENINFO ioctl");
+               goto fail;
+       }
+
+       fbdev->fbvar_new = fbdev->fbvar_old;
+
+       req_w = fbdev->fbvar_new.xres;
+       if (*w != 0)
+               req_w = *w;
+       req_h = fbdev->fbvar_new.yres;
+       if (*h != 0)
+               req_h = *h;
+
+       pret = vout_fbdev_resize(fbdev, req_w, req_h, bpp, 0, 0, 0, 0, buffer_cnt);
+       if (pret == NULL)
+               goto fail;
+
+       printf("%s: %ix%i@%d\n", fbdev_name, fbdev->fbvar_new.xres, fbdev->fbvar_new.yres,
+               fbdev->fbvar_new.bits_per_pixel);
+       *w = fbdev->fbvar_new.xres;
+       *h = fbdev->fbvar_new.yres;
+
+       memset(fbdev->mem, 0, fbdev->mem_size);
+
+       // some checks
+       ret = 0;
+       ret = ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &ret);
+       if (ret != 0)
+               fprintf(stderr, "Warning: vsync doesn't seem to be supported\n");
+
+       if (fbdev->buffer_count > 1) {
+               fbdev->buffer_write = 0;
+               fbdev->fbvar_new.yoffset = fbdev->fbvar_new.yres * (fbdev->buffer_count - 1);
+               ret = ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new);
+               if (ret != 0) {
+                       fbdev->buffer_count = 1;
+                       fprintf(stderr, "Warning: can't pan display, doublebuffering disabled\n");
+               }
+       }
+
+       printf("fbdev initialized.\n");
+       return fbdev;
+
+fail:
+       close(fbdev->fd);
+fail_open:
+       free(fbdev);
+       return NULL;
+}
+
+void vout_fbdev_finish(struct vout_fbdev *fbdev)
+{
+       ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_old);
+       if (fbdev->mem != MAP_FAILED)
+               munmap(fbdev->mem, fbdev->mem_size);
+       if (fbdev->fd >= 0)
+               close(fbdev->fd);
+       fbdev->mem = NULL;
+       fbdev->fd = -1;
+       free(fbdev);
+}
+
diff --git a/pandora/linux/fbdev.h b/pandora/linux/fbdev.h
new file mode 100644 (file)
index 0000000..2db9163
--- /dev/null
@@ -0,0 +1,12 @@
+struct vout_fbdev;
+
+struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int bpp, int buffer_count);
+void *vout_fbdev_flip(struct vout_fbdev *fbdev);
+void  vout_fbdev_wait_vsync(struct vout_fbdev *fbdev);
+void *vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, int bpp,
+                       int left_border, int right_border, int top_border, int bottom_border,
+                       int buffer_count);
+void  vout_fbdev_clear(struct vout_fbdev *fbdev);
+void  vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count);
+int   vout_fbdev_get_fd(struct vout_fbdev *fbdev);
+void  vout_fbdev_finish(struct vout_fbdev *fbdev);
diff --git a/pandora/linux/omapfb.h b/pandora/linux/omapfb.h
new file mode 100644 (file)
index 0000000..f156e3a
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * File: arch/arm/plat-omap/include/mach/omapfb.h
+ *
+ * Framebuffer driver for TI OMAP boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __OMAPFB_H
+#define __OMAPFB_H
+
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
+/* IOCTL commands. */
+
+#define OMAP_IOW(num, dtype)   _IOW('O', num, dtype)
+#define OMAP_IOR(num, dtype)   _IOR('O', num, dtype)
+#define OMAP_IOWR(num, dtype)  _IOWR('O', num, dtype)
+#define OMAP_IO(num)           _IO('O', num)
+
+#define OMAPFB_MIRROR          OMAP_IOW(31, int)
+#define OMAPFB_SYNC_GFX                OMAP_IO(37)
+#define OMAPFB_VSYNC           OMAP_IO(38)
+#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
+#define OMAPFB_GET_CAPS                OMAP_IOR(42, struct omapfb_caps)
+#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
+#define OMAPFB_LCD_TEST                OMAP_IOW(45, int)
+#define OMAPFB_CTRL_TEST       OMAP_IOW(46, int)
+#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
+#define OMAPFB_SET_COLOR_KEY   OMAP_IOW(50, struct omapfb_color_key)
+#define OMAPFB_GET_COLOR_KEY   OMAP_IOW(51, struct omapfb_color_key)
+#define OMAPFB_SETUP_PLANE     OMAP_IOW(52, struct omapfb_plane_info)
+#define OMAPFB_QUERY_PLANE     OMAP_IOW(53, struct omapfb_plane_info)
+#define OMAPFB_UPDATE_WINDOW   OMAP_IOW(54, struct omapfb_update_window)
+#define OMAPFB_SETUP_MEM       OMAP_IOW(55, struct omapfb_mem_info)
+#define OMAPFB_QUERY_MEM       OMAP_IOW(56, struct omapfb_mem_info)
+#define OMAPFB_WAITFORVSYNC    OMAP_IO(57)
+#define OMAPFB_MEMORY_READ     OMAP_IOR(58, struct omapfb_memory_read)
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC      _IOW('F', 0x20, u_int32_t)
+#endif
+
+#define OMAPFB_CAPS_GENERIC_MASK       0x00000fff
+#define OMAPFB_CAPS_LCDC_MASK          0x00fff000
+#define OMAPFB_CAPS_PANEL_MASK         0xff000000
+
+#define OMAPFB_CAPS_MANUAL_UPDATE      0x00001000
+#define OMAPFB_CAPS_TEARSYNC           0x00002000
+#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
+#define OMAPFB_CAPS_PLANE_SCALE                0x00008000
+#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE        0x00010000
+#define OMAPFB_CAPS_WINDOW_SCALE       0x00020000
+#define OMAPFB_CAPS_WINDOW_OVERLAY     0x00040000
+#define OMAPFB_CAPS_WINDOW_ROTATE      0x00080000
+#define OMAPFB_CAPS_SET_BACKLIGHT      0x01000000
+
+/* Values from DSP must map to lower 16-bits */
+#define OMAPFB_FORMAT_MASK             0x00ff
+#define OMAPFB_FORMAT_FLAG_DOUBLE      0x0100
+#define OMAPFB_FORMAT_FLAG_TEARSYNC    0x0200
+#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
+#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY      0x0800
+#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY     0x1000
+
+#define OMAPFB_EVENT_READY     1
+#define OMAPFB_EVENT_DISABLED  2
+
+#define OMAPFB_MEMTYPE_SDRAM           0
+#define OMAPFB_MEMTYPE_SRAM            1
+#define OMAPFB_MEMTYPE_MAX             1
+
+enum omapfb_color_format {
+       OMAPFB_COLOR_RGB565 = 0,
+       OMAPFB_COLOR_YUV422,
+       OMAPFB_COLOR_YUV420,
+       OMAPFB_COLOR_CLUT_8BPP,
+       OMAPFB_COLOR_CLUT_4BPP,
+       OMAPFB_COLOR_CLUT_2BPP,
+       OMAPFB_COLOR_CLUT_1BPP,
+       OMAPFB_COLOR_RGB444,
+       OMAPFB_COLOR_YUY422,
+
+       OMAPFB_COLOR_ARGB16,
+       OMAPFB_COLOR_RGB24U,    /* RGB24, 32-bit container */
+       OMAPFB_COLOR_RGB24P,    /* RGB24, 24-bit container */
+       OMAPFB_COLOR_ARGB32,
+       OMAPFB_COLOR_RGBA32,
+       OMAPFB_COLOR_RGBX32,
+};
+
+struct omapfb_update_window {
+       __u32 x, y;
+       __u32 width, height;
+       __u32 format;
+       __u32 out_x, out_y;
+       __u32 out_width, out_height;
+       __u32 reserved[8];
+};
+
+struct omapfb_update_window_old {
+       __u32 x, y;
+       __u32 width, height;
+       __u32 format;
+};
+
+enum omapfb_plane {
+       OMAPFB_PLANE_GFX = 0,
+       OMAPFB_PLANE_VID1,
+       OMAPFB_PLANE_VID2,
+};
+
+enum omapfb_channel_out {
+       OMAPFB_CHANNEL_OUT_LCD = 0,
+       OMAPFB_CHANNEL_OUT_DIGIT,
+};
+
+struct omapfb_plane_info {
+       __u32 pos_x;
+       __u32 pos_y;
+       __u8  enabled;
+       __u8  channel_out;
+       __u8  mirror;
+       __u8  reserved1;
+       __u32 out_width;
+       __u32 out_height;
+       __u32 reserved2[12];
+};
+
+struct omapfb_mem_info {
+       __u32 size;
+       __u8  type;
+       __u8  reserved[3];
+};
+
+struct omapfb_caps {
+       __u32 ctrl;
+       __u32 plane_color;
+       __u32 wnd_color;
+};
+
+enum omapfb_color_key_type {
+       OMAPFB_COLOR_KEY_DISABLED = 0,
+       OMAPFB_COLOR_KEY_GFX_DST,
+       OMAPFB_COLOR_KEY_VID_SRC,
+};
+
+struct omapfb_color_key {
+       __u8  channel_out;
+       __u32 background;
+       __u32 trans_key;
+       __u8  key_type;
+};
+
+enum omapfb_update_mode {
+       OMAPFB_UPDATE_DISABLED = 0,
+       OMAPFB_AUTO_UPDATE,
+       OMAPFB_MANUAL_UPDATE
+};
+
+struct omapfb_memory_read {
+       __u16 x;
+       __u16 y;
+       __u16 w;
+       __u16 h;
+       size_t buffer_size;
+       void *buffer;
+};
+
+#ifdef __KERNEL__
+
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/mutex.h>
+
+#include <mach/board.h>
+
+#define OMAP_LCDC_INV_VSYNC             0x0001
+#define OMAP_LCDC_INV_HSYNC             0x0002
+#define OMAP_LCDC_INV_PIX_CLOCK         0x0004
+#define OMAP_LCDC_INV_OUTPUT_EN         0x0008
+#define OMAP_LCDC_HSVS_RISING_EDGE      0x0010
+#define OMAP_LCDC_HSVS_OPPOSITE         0x0020
+
+#define OMAP_LCDC_SIGNAL_MASK          0x003f
+
+#define OMAP_LCDC_PANEL_TFT            0x0100
+
+#define OMAPFB_PLANE_XRES_MIN          8
+#define OMAPFB_PLANE_YRES_MIN          8
+
+#ifdef CONFIG_ARCH_OMAP1
+#define OMAPFB_PLANE_NUM               1
+#else
+#define OMAPFB_PLANE_NUM               3
+#endif
+
+struct omapfb_device;
+
+struct lcd_panel {
+       const char      *name;
+       int             config;         /* TFT/STN, signal inversion */
+       int             bpp;            /* Pixel format in fb mem */
+       int             data_lines;     /* Lines on LCD HW interface */
+
+       int             x_res, y_res;
+       int             pixel_clock;    /* In kHz */
+       int             hsw;            /* Horizontal synchronization
+                                          pulse width */
+       int             hfp;            /* Horizontal front porch */
+       int             hbp;            /* Horizontal back porch */
+       int             vsw;            /* Vertical synchronization
+                                          pulse width */
+       int             vfp;            /* Vertical front porch */
+       int             vbp;            /* Vertical back porch */
+       int             acb;            /* ac-bias pin frequency */
+       int             pcd;            /* pixel clock divider.
+                                          Obsolete use pixel_clock instead */
+
+       int             (*init)         (struct lcd_panel *panel,
+                                        struct omapfb_device *fbdev);
+       void            (*cleanup)      (struct lcd_panel *panel);
+       int             (*enable)       (struct lcd_panel *panel);
+       void            (*disable)      (struct lcd_panel *panel);
+       unsigned long   (*get_caps)     (struct lcd_panel *panel);
+       int             (*set_bklight_level)(struct lcd_panel *panel,
+                                            unsigned int level);
+       unsigned int    (*get_bklight_level)(struct lcd_panel *panel);
+       unsigned int    (*get_bklight_max)  (struct lcd_panel *panel);
+       int             (*run_test)     (struct lcd_panel *panel, int test_num);
+};
+
+struct extif_timings {
+       int cs_on_time;
+       int cs_off_time;
+       int we_on_time;
+       int we_off_time;
+       int re_on_time;
+       int re_off_time;
+       int we_cycle_time;
+       int re_cycle_time;
+       int cs_pulse_width;
+       int access_time;
+
+       int clk_div;
+
+       u32 tim[5];             /* set by extif->convert_timings */
+
+       int converted;
+};
+
+struct lcd_ctrl_extif {
+       int  (*init)            (struct omapfb_device *fbdev);
+       void (*cleanup)         (void);
+       void (*get_clk_info)    (u32 *clk_period, u32 *max_clk_div);
+       unsigned long (*get_max_tx_rate)(void);
+       int  (*convert_timings) (struct extif_timings *timings);
+       void (*set_timings)     (const struct extif_timings *timings);
+       void (*set_bits_per_cycle)(int bpc);
+       void (*write_command)   (const void *buf, unsigned int len);
+       void (*read_data)       (void *buf, unsigned int len);
+       void (*write_data)      (const void *buf, unsigned int len);
+       void (*transfer_area)   (int width, int height,
+                                void (callback)(void * data), void *data);
+       int  (*setup_tearsync)  (unsigned pin_cnt,
+                                unsigned hs_pulse_time, unsigned vs_pulse_time,
+                                int hs_pol_inv, int vs_pol_inv, int div);
+       int  (*enable_tearsync) (int enable, unsigned line);
+
+       unsigned long           max_transmit_size;
+};
+
+struct omapfb_notifier_block {
+       struct notifier_block   nb;
+       void                    *data;
+       int                     plane_idx;
+};
+
+typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
+                                         unsigned long event,
+                                         void *fbi);
+
+struct omapfb_mem_region {
+       u32             paddr;
+       void __iomem    *vaddr;
+       unsigned long   size;
+       u8              type;           /* OMAPFB_PLANE_MEM_* */
+       enum omapfb_color_format format;/* OMAPFB_COLOR_* */
+       unsigned        format_used:1;  /* Must be set when format is set.
+                                        * Needed b/c of the badly chosen 0
+                                        * base for OMAPFB_COLOR_* values
+                                        */
+       unsigned        alloc:1;        /* allocated by the driver */
+       unsigned        map:1;          /* kernel mapped by the driver */
+};
+
+struct omapfb_mem_desc {
+       int                             region_cnt;
+       struct omapfb_mem_region        region[OMAPFB_PLANE_NUM];
+};
+
+struct lcd_ctrl {
+       const char      *name;
+       void            *data;
+
+       int             (*init)           (struct omapfb_device *fbdev,
+                                          int ext_mode,
+                                          struct omapfb_mem_desc *req_md);
+       void            (*cleanup)        (void);
+       void            (*bind_client)    (struct omapfb_notifier_block *nb);
+       void            (*get_caps)       (int plane, struct omapfb_caps *caps);
+       int             (*set_update_mode)(enum omapfb_update_mode mode);
+       enum omapfb_update_mode (*get_update_mode)(void);
+       int             (*setup_plane)    (int plane, int channel_out,
+                                          unsigned long offset,
+                                          int screen_width,
+                                          int pos_x, int pos_y, int width,
+                                          int height, int color_mode);
+       int             (*set_rotate)     (int angle);
+       int             (*setup_mem)      (int plane, size_t size,
+                                          int mem_type, unsigned long *paddr);
+       int             (*mmap)           (struct fb_info *info,
+                                          struct vm_area_struct *vma);
+       int             (*set_scale)      (int plane,
+                                          int orig_width, int orig_height,
+                                          int out_width, int out_height);
+       int             (*enable_plane)   (int plane, int enable);
+       int             (*update_window)  (struct fb_info *fbi,
+                                          struct omapfb_update_window *win,
+                                          void (*callback)(void *),
+                                          void *callback_data);
+       void            (*sync)           (void);
+       void            (*suspend)        (void);
+       void            (*resume)         (void);
+       int             (*run_test)       (int test_num);
+       int             (*setcolreg)      (u_int regno, u16 red, u16 green,
+                                          u16 blue, u16 transp,
+                                          int update_hw_mem);
+       int             (*set_color_key)  (struct omapfb_color_key *ck);
+       int             (*get_color_key)  (struct omapfb_color_key *ck);
+};
+
+enum omapfb_state {
+       OMAPFB_DISABLED = 0,
+       OMAPFB_SUSPENDED= 99,
+       OMAPFB_ACTIVE   = 100
+};
+
+struct omapfb_plane_struct {
+       int                             idx;
+       struct omapfb_plane_info        info;
+       enum omapfb_color_format        color_mode;
+       struct omapfb_device            *fbdev;
+};
+
+struct omapfb_device {
+       int                     state;
+       int                     ext_lcdc;               /* Using external
+                                                           LCD controller */
+       struct mutex            rqueue_mutex;
+
+       int                     palette_size;
+       u32                     pseudo_palette[17];
+
+       struct lcd_panel        *panel;                 /* LCD panel */
+       const struct lcd_ctrl   *ctrl;                  /* LCD controller */
+       const struct lcd_ctrl   *int_ctrl;              /* internal LCD ctrl */
+       struct lcd_ctrl_extif   *ext_if;                /* LCD ctrl external
+                                                          interface */
+       struct device           *dev;
+       struct fb_var_screeninfo        new_var;        /* for mode changes */
+
+       struct omapfb_mem_desc          mem_desc;
+       struct fb_info                  *fb_info[OMAPFB_PLANE_NUM];
+};
+
+struct omapfb_platform_data {
+       struct omap_lcd_config          lcd;
+       struct omapfb_mem_desc          mem_desc;
+       void                            *ctrl_platform_data;
+};
+
+#ifdef CONFIG_ARCH_OMAP1
+extern struct lcd_ctrl omap1_lcd_ctrl;
+#else
+extern struct lcd_ctrl omap2_disp_ctrl;
+#endif
+
+extern void omapfb_set_platform_data(struct omapfb_platform_data *data);
+
+extern void omapfb_reserve_sdram(void);
+extern void omapfb_register_panel(struct lcd_panel *panel);
+extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+extern void omapfb_notify_clients(struct omapfb_device *fbdev,
+                                 unsigned long event);
+extern int  omapfb_register_client(struct omapfb_notifier_block *nb,
+                                  omapfb_notifier_callback_t callback,
+                                  void *callback_data);
+extern int  omapfb_unregister_client(struct omapfb_notifier_block *nb);
+extern int  omapfb_update_window_async(struct fb_info *fbi,
+                                      struct omapfb_update_window *win,
+                                      void (*callback)(void *),
+                                      void *callback_data);
+
+/* in arch/arm/plat-omap/fb.c */
+extern void omapfb_set_ctrl_platform_data(void *pdata);
+
+#endif /* __KERNEL__ */
+
+#endif /* __OMAPFB_H */
diff --git a/pandora/linux/xenv.c b/pandora/linux/xenv.c
new file mode 100644 (file)
index 0000000..8295b2c
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * (C) Gražvydas "notaz" Ignotas, 2009-2011
+ *
+ * This work is licensed under the terms of any of these licenses
+ * (at your option):
+ *  - GNU GPL, version 2 or later.
+ *  - GNU LGPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+
+#include <dlfcn.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/XKBlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <linux/kd.h>
+
+#define PFX "xenv: "
+
+#define FPTR(f) typeof(f) * p##f
+#define FPTR_LINK(xf, dl, f) { \
+       xf.p##f = dlsym(dl, #f); \
+       if (xf.p##f == NULL) { \
+               fprintf(stderr, "missing symbol: %s\n", #f); \
+               goto fail; \
+       } \
+}
+
+struct xstuff {
+       Display *display;
+       FPTR(XCreateBitmapFromData);
+       FPTR(XCreatePixmapCursor);
+       FPTR(XFreePixmap);
+       FPTR(XOpenDisplay);
+       FPTR(XDisplayName);
+       FPTR(XCloseDisplay);
+       FPTR(XCreateSimpleWindow);
+       FPTR(XChangeWindowAttributes);
+       FPTR(XSelectInput);
+       FPTR(XMapWindow);
+       FPTR(XNextEvent);
+       FPTR(XCheckTypedEvent);
+       FPTR(XUnmapWindow);
+       FPTR(XGrabKeyboard);
+       FPTR(XPending);
+       FPTR(XLookupKeysym);
+       FPTR(XkbSetDetectableAutoRepeat);
+};
+
+static struct xstuff g_xstuff;
+
+static Cursor transparent_cursor(struct xstuff *xf, Display *display, Window win)
+{
+       Cursor cursor;
+       Pixmap pix;
+       XColor dummy;
+       char d = 0;
+
+       memset(&dummy, 0, sizeof(dummy));
+       pix = xf->pXCreateBitmapFromData(display, win, &d, 1, 1);
+       cursor = xf->pXCreatePixmapCursor(display, pix, pix,
+                       &dummy, &dummy, 0, 0);
+       xf->pXFreePixmap(display, pix);
+       return cursor;
+}
+
+static int x11h_init(void)
+{
+       unsigned int display_width, display_height;
+       Display *display;
+       XSetWindowAttributes attributes;
+       Window win;
+       Visual *visual;
+       void *x11lib;
+       int screen;
+
+       memset(&g_xstuff, 0, sizeof(g_xstuff));
+       x11lib = dlopen("libX11.so.6", RTLD_LAZY);
+       if (x11lib == NULL) {
+               fprintf(stderr, "libX11.so load failed:\n%s\n", dlerror());
+               goto fail;
+       }
+       FPTR_LINK(g_xstuff, x11lib, XCreateBitmapFromData);
+       FPTR_LINK(g_xstuff, x11lib, XCreatePixmapCursor);
+       FPTR_LINK(g_xstuff, x11lib, XFreePixmap);
+       FPTR_LINK(g_xstuff, x11lib, XOpenDisplay);
+       FPTR_LINK(g_xstuff, x11lib, XDisplayName);
+       FPTR_LINK(g_xstuff, x11lib, XCloseDisplay);
+       FPTR_LINK(g_xstuff, x11lib, XCreateSimpleWindow);
+       FPTR_LINK(g_xstuff, x11lib, XChangeWindowAttributes);
+       FPTR_LINK(g_xstuff, x11lib, XSelectInput);
+       FPTR_LINK(g_xstuff, x11lib, XMapWindow);
+       FPTR_LINK(g_xstuff, x11lib, XNextEvent);
+       FPTR_LINK(g_xstuff, x11lib, XCheckTypedEvent);
+       FPTR_LINK(g_xstuff, x11lib, XUnmapWindow);
+       FPTR_LINK(g_xstuff, x11lib, XGrabKeyboard);
+       FPTR_LINK(g_xstuff, x11lib, XPending);
+       FPTR_LINK(g_xstuff, x11lib, XLookupKeysym);
+       FPTR_LINK(g_xstuff, x11lib, XkbSetDetectableAutoRepeat);
+
+       //XInitThreads();
+
+       g_xstuff.display = display = g_xstuff.pXOpenDisplay(NULL);
+       if (display == NULL)
+       {
+               fprintf(stderr, "cannot connect to X server %s, X handling disabled.\n",
+                               g_xstuff.pXDisplayName(NULL));
+               goto fail2;
+       }
+
+       visual = DefaultVisual(display, 0);
+       if (visual->class != TrueColor)
+               fprintf(stderr, PFX "warning: non true color visual\n");
+
+       printf(PFX "X vendor: %s, rel: %d, display: %s, protocol ver: %d.%d\n", ServerVendor(display),
+               VendorRelease(display), DisplayString(display), ProtocolVersion(display),
+               ProtocolRevision(display));
+
+       screen = DefaultScreen(display);
+
+       display_width = DisplayWidth(display, screen);
+       display_height = DisplayHeight(display, screen);
+       printf(PFX "display is %dx%d\n", display_width, display_height);
+
+       win = g_xstuff.pXCreateSimpleWindow(display,
+                       RootWindow(display, screen),
+                       0, 0, display_width, display_height, 0,
+                       BlackPixel(display, screen),
+                       BlackPixel(display, screen));
+
+       attributes.override_redirect = True;
+       attributes.cursor = transparent_cursor(&g_xstuff, display, win);
+       g_xstuff.pXChangeWindowAttributes(display, win, CWOverrideRedirect | CWCursor, &attributes);
+
+       g_xstuff.pXSelectInput(display, win, ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask);
+       g_xstuff.pXMapWindow(display, win);
+       g_xstuff.pXGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+       g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
+       // XSetIOErrorHandler
+
+       return 0;
+fail2:
+       dlclose(x11lib);
+fail:
+       g_xstuff.display = NULL;
+       fprintf(stderr, "x11 handling disabled.\n");
+       return -1;
+}
+
+static int x11h_update(int *is_down)
+{
+       XEvent evt;
+
+       while (g_xstuff.pXPending(g_xstuff.display))
+       {
+               g_xstuff.pXNextEvent(g_xstuff.display, &evt);
+               switch (evt.type)
+               {
+                       case Expose:
+                               while (g_xstuff.pXCheckTypedEvent(g_xstuff.display, Expose, &evt))
+                                       ;
+                               break;
+
+                       case KeyPress:
+                               *is_down = 1;
+                               return g_xstuff.pXLookupKeysym(&evt.xkey, 0);
+
+                       case KeyRelease:
+                               *is_down = 0;
+                               return g_xstuff.pXLookupKeysym(&evt.xkey, 0);
+                               // printf("press %d\n", evt.xkey.keycode);
+               }
+       }
+
+       return NoSymbol;
+}
+
+static struct termios g_kbd_termios_saved;
+static int g_kbdfd;
+
+static int tty_init(void)
+{
+       struct termios kbd_termios;
+       int mode;
+
+       g_kbdfd = open("/dev/tty", O_RDWR);
+       if (g_kbdfd == -1) {
+               perror(PFX "open /dev/tty");
+               return -1;
+       }
+
+       if (ioctl(g_kbdfd, KDGETMODE, &mode) == -1) {
+               perror(PFX "(not hiding FB): KDGETMODE");
+               goto fail;
+       }
+
+       if (tcgetattr(g_kbdfd, &kbd_termios) == -1) {
+               perror(PFX "tcgetattr");
+               goto fail;
+       }
+
+       g_kbd_termios_saved = kbd_termios;
+       kbd_termios.c_lflag &= ~(ICANON | ECHO); // | ISIG);
+       kbd_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
+       kbd_termios.c_cc[VMIN] = 0;
+       kbd_termios.c_cc[VTIME] = 0;
+
+       if (tcsetattr(g_kbdfd, TCSAFLUSH, &kbd_termios) == -1) {
+               perror(PFX "tcsetattr");
+               goto fail;
+       }
+
+       if (ioctl(g_kbdfd, KDSETMODE, KD_GRAPHICS) == -1) {
+               perror(PFX "KDSETMODE KD_GRAPHICS");
+               tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved);
+               goto fail;
+       }
+
+       return 0;
+
+fail:
+       close(g_kbdfd);
+       g_kbdfd = -1;
+       return -1;
+}
+
+static void tty_end(void)
+{
+       if (g_kbdfd <= 0)
+               return;
+
+       if (ioctl(g_kbdfd, KDSETMODE, KD_TEXT) == -1)
+               perror(PFX "KDSETMODE KD_TEXT");
+
+       if (tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved) == -1)
+               perror(PFX "tcsetattr");
+
+       close(g_kbdfd);
+       g_kbdfd = -1;
+}
+
+int xenv_init(void)
+{
+       int ret;
+
+       ret = x11h_init();
+       if (ret == 0)
+               return 0;
+
+       ret = tty_init();
+       if (ret == 0)
+               return 0;
+
+       fprintf(stderr, PFX "error: both x11h_init and tty_init failed\n");
+       return -1;
+}
+
+int xenv_update(int *is_down)
+{
+       if (g_xstuff.display)
+               return x11h_update(is_down);
+
+       // TODO: read tty?
+       return -1;
+}
+
+void xenv_finish(void)
+{
+       // TODO: cleanup X?
+       tty_end();
+}
diff --git a/pandora/linux/xenv.h b/pandora/linux/xenv.h
new file mode 100644 (file)
index 0000000..948381e
--- /dev/null
@@ -0,0 +1,5 @@
+
+int  xenv_init(void);
+int  xenv_update(int *is_down);
+void xenv_finish(void);
+
diff --git a/pandora/pnd.c b/pandora/pnd.c
new file mode 100644 (file)
index 0000000..c845831
--- /dev/null
@@ -0,0 +1,315 @@
+/* gameplaySP - pandora backend
+ *
+ * Copyright (C) 2011 notaz <notasas@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "../common.h"
+#include <X11/keysym.h>
+#include "linux/omapfb.h" //
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "linux/fbdev.h"
+#include "linux/xenv.h"
+
+enum gpsp_key {
+  GKEY_UP       = 1 << 0,
+  GKEY_LEFT     = 1 << 1,
+  GKEY_DOWN     = 1 << 2,
+  GKEY_RIGHT    = 1 << 3,
+  GKEY_START    = 1 << 4,
+  GKEY_SELECT   = 1 << 5,
+  GKEY_L        = 1 << 6,
+  GKEY_R        = 1 << 7,
+  GKEY_A        = 1 << 8,
+  GKEY_B        = 1 << 9,
+  GKEY_X        = 1 << 10,
+  GKEY_Y        = 1 << 11,
+  GKEY_1        = 1 << 12,
+  GKEY_2        = 1 << 13,
+  GKEY_3        = 1 << 14,
+  GKEY_4        = 1 << 15,
+  GKEY_MENU     = 1 << 16,
+};
+
+u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT] =
+{
+  GKEY_UP,
+  GKEY_LEFT,
+  GKEY_DOWN,
+  GKEY_RIGHT,
+  GKEY_START,
+  GKEY_SELECT,
+  GKEY_L,
+  GKEY_R,
+  GKEY_A,
+  GKEY_B,
+  GKEY_X,
+  GKEY_Y,
+  GKEY_1,
+  GKEY_2,
+  GKEY_3,
+  GKEY_4,
+  GKEY_MENU,
+};
+
+u32 gamepad_config_map[PLAT_BUTTON_COUNT] =
+{
+  BUTTON_ID_UP,                 // Up
+  BUTTON_ID_LEFT,               // Left
+  BUTTON_ID_DOWN,               // Down
+  BUTTON_ID_RIGHT,              // Right
+  BUTTON_ID_START,              // Start
+  BUTTON_ID_SELECT,             // Select
+  BUTTON_ID_L,                  // Ltrigger
+  BUTTON_ID_R,                  // Rtrigger
+  BUTTON_ID_FPS,                // A
+  BUTTON_ID_A,                  // B
+  BUTTON_ID_B,                  // X
+  BUTTON_ID_MENU,               // Y
+  BUTTON_ID_SAVESTATE,          // 1
+  BUTTON_ID_LOADSTATE,          // 2
+  BUTTON_ID_FASTFORWARD,        // 3
+  BUTTON_ID_NONE,               // 4
+  BUTTON_ID_MENU                // Space
+};
+
+static const u32 xk_to_gkey[] = {
+  XK_Up, XK_Left, XK_Down, XK_Right, XK_Alt_L, XK_Control_L,
+  XK_Shift_L, XK_Control_R, XK_Home, XK_End, XK_Page_Down, XK_Page_Up,
+  XK_1, XK_2, XK_3, XK_4, XK_space,
+};
+
+static const u8 gkey_to_cursor[32] = {
+  [0 ... 31] = CURSOR_NONE,
+  [0] = CURSOR_UP, CURSOR_LEFT, CURSOR_DOWN, CURSOR_RIGHT, CURSOR_NONE, CURSOR_NONE,
+  CURSOR_L, CURSOR_R, CURSOR_SELECT, CURSOR_SELECT, CURSOR_EXIT, CURSOR_BACK,
+};
+
+struct vout_fbdev *fb;
+
+static int omap_setup_layer(int fd, int enabled, int x, int y, int w, int h, int first_call)
+{
+  struct omapfb_plane_info pi = { 0, };
+  struct omapfb_mem_info mi = { 0, };
+  int ret;
+
+  ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);
+  if (ret != 0) {
+    perror("QUERY_PLANE");
+    return -1;
+  }
+
+  ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);
+  if (ret != 0) {
+    perror("QUERY_MEM");
+    return -1;
+  }
+
+  /* must disable when changing stuff */
+  if (pi.enabled) {
+    pi.enabled = 0;
+    ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
+    if (ret != 0)
+      perror("SETUP_PLANE");
+  }
+
+  if (first_call) {
+    mi.size = 640*512*3*3;
+    ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
+    if (ret != 0) {
+      perror("SETUP_MEM");
+      return -1;
+    }
+  }
+
+  pi.pos_x = x;
+  pi.pos_y = y;
+  pi.out_width = w;
+  pi.out_height = h;
+  pi.enabled = enabled;
+
+  ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
+  if (ret != 0) {
+    perror("SETUP_PLANE");
+    return -1;
+  }
+
+  return 0;
+}
+
+void gpsp_plat_init(void)
+{
+  int ret, w, h, fd;
+  const char *layer_fb_name;
+
+  ret = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);
+  if (ret != 0) {
+    fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
+    exit(1);
+  }
+
+  layer_fb_name = getenv("FBDEV_LAYER");
+  if (layer_fb_name == NULL)
+    layer_fb_name = "/dev/fb1";
+
+  ret = xenv_init();
+  if (ret != 0) {
+    fprintf(stderr, "xenv_init failed with %d\n", ret);
+    exit(1);
+  }
+
+  // must set the layer up first to be able to use it
+  fd = open(layer_fb_name, O_RDWR);
+  if (fd == -1) {
+    fprintf(stderr, "%s: ", layer_fb_name);
+    perror("open");
+    exit(1);
+  }
+
+  ret = omap_setup_layer(fd, 0, 0, 0, 400, 272, 1);
+  close(fd);
+  if (ret != 0) {
+    fprintf(stderr, "failed to set up layer, exiting.\n");
+    exit(1);
+  }
+
+  w = 240;
+  h = 160;
+  fb = vout_fbdev_init("/dev/fb1", &w, &h, 16, 4);
+  if (fb == NULL) {
+    fprintf(stderr, "vout_fbdev_init failed\n");
+    exit(1);
+  }
+
+  // default to 3x scale
+  screen_scale = 2;
+}
+
+void gpsp_plat_quit(void)
+{
+  xenv_finish();
+  omap_setup_layer(vout_fbdev_get_fd(fb), 0, 0, 0, 0, 0, 0);
+  vout_fbdev_finish(fb);
+  SDL_Quit();
+}
+
+u32 gpsp_plat_joystick_read(void)
+{
+  static int gkeystate;
+  int key, is_down, i;
+  int gkey = -1;
+  
+  key = xenv_update(&is_down);
+  for (i = 0; i < sizeof(xk_to_gkey) / sizeof(xk_to_gkey[0]); i++) {
+    if (key == xk_to_gkey[i]) {
+      gkey = i;
+      break;
+    }
+  }
+
+  if (gkey >= 0) {
+    if (is_down)
+      gkeystate |= 1 << gkey;
+    else
+      gkeystate &= ~(1 << gkey);
+  }
+  
+  return gkeystate;
+}
+
+u32 gpsp_plat_buttons_to_cursor(u32 buttons)
+{
+  int i;
+
+  if (buttons == 0)
+    return CURSOR_NONE;
+
+  for (i = 0; (buttons & 1) == 0; i++, buttons >>= 1)
+    ;
+
+  return gkey_to_cursor[i];
+}
+
+static void set_filter(int is_filtered)
+{
+  static int was_filtered = -1;
+  char buf[128];
+
+  if (is_filtered == was_filtered)
+    return;
+
+  snprintf(buf, sizeof(buf), "sudo -n /usr/pandora/scripts/op_videofir.sh %s",
+    is_filtered ? "default" : "none");
+  system(buf);
+  was_filtered = is_filtered;
+}
+
+void *fb_flip_screen(void)
+{
+  return vout_fbdev_flip(fb);
+}
+
+void fb_wait_vsync(void)
+{
+  vout_fbdev_wait_vsync(fb);
+}
+
+void fb_set_mode(int w, int h, int buffers, int scale, int filter)
+{
+  int lx, ly, lw = w, lh = h;
+  switch (scale) {
+    case 0:
+      lw = w;
+      lh = h;
+      break;
+    case 1:
+      lw = w * 2;
+      lh = h * 2;
+      break;
+    case 2:
+      lw = w * 3;
+      lh = h * 3;
+      break;
+    case 3:
+      lw = 800;
+      lh = 480;
+      break;
+    case 15:
+      lw = w * 2;
+      lh = h + h /2;
+      break;
+    default:
+      fprintf(stderr, "unknown scale: %d\n", scale);
+      break;
+  }
+  if (lw > 800)
+    lw = 800;
+  if (lh > 480)
+    lh = 480;
+  lx = 800 / 2 - lw / 2;
+  ly = 480 / 2 - lh / 2;
+
+  omap_setup_layer(vout_fbdev_get_fd(fb), 1, lx, ly, lw, lh, 0);
+  set_filter(filter);
+
+  vout_fbdev_resize(fb, w, h, 16, 0, 0, 0, 0, buffers);
+}
+
+// vim:shiftwidth=2:expandtab
diff --git a/pandora/pnd.h b/pandora/pnd.h
new file mode 100644 (file)
index 0000000..2161756
--- /dev/null
@@ -0,0 +1,12 @@
+void gpsp_plat_init(void);
+void gpsp_plat_quit(void);
+
+u32 gpsp_plat_joystick_read(void);
+u32 gpsp_plat_buttons_to_cursor(u32 buttons);
+
+#define PLAT_BUTTON_COUNT 17
+extern u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT];
+
+void *fb_flip_screen(void);
+void fb_set_mode(int w, int h, int buffers, int scale, int filter);
+void fb_wait_vsync(void);
diff --git a/video.c b/video.c
index 59f3e69..a33accf 100644 (file)
--- a/video.c
+++ b/video.c
@@ -102,6 +102,16 @@ const u32 screen_pitch = 320;
 #define get_screen_pitch()                                                    \
   screen_pitch                                                                \
 
 #define get_screen_pitch()                                                    \
   screen_pitch                                                                \
 
+#elif defined(PND_BUILD)
+
+static u16 *screen_pixels = NULL;
+
+#define get_screen_pixels()                                                   \
+  screen_pixels                                                               \
+
+#define get_screen_pitch()                                                    \
+  resolution_width                                                            \
+
 #else
 
 #ifdef GP2X_BUILD
 #else
 
 #ifdef GP2X_BUILD
@@ -3392,6 +3402,13 @@ no_clean:
   screen_pixels = (u16 *)gpsp_gp2x_screen + screen_offset;
 }
 
   screen_pixels = (u16 *)gpsp_gp2x_screen + screen_offset;
 }
 
+#elif defined(PND_BUILD)
+
+void flip_screen()
+{
+  screen_pixels = fb_flip_screen();
+}
+
 #else
 
 #define integer_scale_copy_2()                                                \
 #else
 
 #define integer_scale_copy_2()                                                \
@@ -3601,7 +3618,7 @@ void init_video()
   GE_CMD(NOP, 0);
 }
 
   GE_CMD(NOP, 0);
 }
 
-#elif defined(WIZ_BUILD)
+#elif defined(WIZ_BUILD) || defined(PND_BUILD)
 
 void init_video()
 {
 
 void init_video()
 {
@@ -3796,6 +3813,42 @@ void clear_screen(u16 color)
     *p++ = col;
 }
 
     *p++ = col;
 }
 
+#elif defined(PND_BUILD)
+
+void video_resolution_large()
+{
+  resolution_width = 400;
+  resolution_height = 272;
+
+  fb_set_mode(400, 272, 1, 15, screen_filter);
+  flip_screen();
+  clear_screen(0);
+}
+
+void video_resolution_small()
+{
+  resolution_width = 240;
+  resolution_height = 160;
+
+  fb_set_mode(240, 160, 4, screen_scale, screen_filter);
+  flip_screen();
+  clear_screen(0);
+}
+
+void set_gba_resolution(video_scale_type scale)
+{
+  screen_scale = scale;
+}
+
+void clear_screen(u16 color)
+{
+  u32 col = ((u32)color << 16) | color;
+  u32 *p = (u32 *)get_screen_pixels();
+  int c = resolution_width * resolution_height / 2;
+  while (c-- > 0)
+    *p++ = col;
+}
+
 #else
 
 void video_resolution_large()
 #else
 
 void video_resolution_large()