#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
+#include <ctype.h>
#include <sys/time.h>
#include <SDL/SDL.h>
#include "pmsdl.h"
+#include "common/input.h"
#include "linux/fbdev.h"
-
-#define err(fmt, ...) fprintf(stderr, "psdl: " fmt "\n", ##__VA_ARGS__)
-#if 0
-#define trace(fmt, ...) printf(" %s(" fmt ")\n", __FUNCTION__, ##__VA_ARGS__)
-#define dbg err
-#else
-#define trace(...)
-#define dbg(...)
-#endif
+#include "linux/oshide.h"
static SDL_Surface *g_screen;
static void *g_screen_fbp;
static Uint16 g_8bpp_pal[256];
static Uint32 g_start_ticks;
-static Uint8 g_keystate[SDLK_LAST];
static inline int min(int v1, int v2)
{
return v1 < v2 ? v1 : v2;
}
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-
static SDL_Surface *alloc_surface(int w, int h, int bpp)
{
// SDL has some pointer overuse, every surface has a format,
return &ret->s;
}
+static char *sskip(char *p)
+{
+ while (*p && isspace(*p))
+ p++;
+ return p;
+}
+
+static char *nsskip(char *p)
+{
+ while (*p && !isspace(*p))
+ p++;
+ return p;
+}
+
+static int check_token(const char *p, const char *token)
+{
+ int tlen = strlen(token);
+ return strncasecmp(p, token, tlen) == 0 && isspace(p[tlen]);
+}
+
+static void do_config(void)
+{
+ char buff[256];
+ FILE *f;
+
+ f = fopen("pmsdl.cfg", "r");
+ if (f == NULL)
+ return;
+
+ while (!feof(f)) {
+ char *p, *line = fgets(buff, sizeof(buff), f);
+ if (line == NULL)
+ break;
+ p = line = sskip(line);
+ if (*p == '#')
+ continue;
+
+ if (check_token(p, "bind")) {
+ char *key, *key_end, *sdlkey, *sdlkey_end;
+ key = sskip(p + 5);
+ key_end = nsskip(key);
+ p = sskip(key_end);
+ if (*p != '=')
+ goto bad;
+ sdlkey = sskip(p + 1);
+ sdlkey_end = nsskip(sdlkey);
+ p = sskip(sdlkey_end);
+ if (*key == 0 || *sdlkey == 0 || *p != 0)
+ goto bad;
+ *key_end = *sdlkey_end = 0;
+
+ pmsdl_input_bind(key, sdlkey);
+ continue;
+ }
+
+bad:
+ err("config: failed to parse: %s", line);
+ }
+ fclose(f);
+}
+
DECLSPEC int SDLCALL
SDL_Init(Uint32 flags)
{
trace("%08x", flags);
+ if (g_start_ticks == 0) {
+ pmsdl_input_init();
+ oshide_init();
+ do_config();
+ }
+
g_start_ticks = 0;
g_start_ticks = SDL_GetTicks();
SDL_Quit(void)
{
trace("");
+
+ if (g_start_ticks != 0) {
+ oshide_finish();
+ g_start_ticks = 0;
+ }
}
DECLSPEC int SDLCALL
trace("%d, %d, %d, %08x", width, height, bpp, flags);
+ if (bpp == 0)
+ bpp = 16;
+
if (bpp != 8 && bpp != 16) {
err("unsupported bpp: %d\n", bpp);
return NULL;
if (screen->format->BitsPerPixel == 8) {
int l = screen->pitch * screen->h;
-#if 1
+#ifdef __arm__
do_clut(g_screen_fbp, screen->pixels, g_8bpp_pal, l);
#else
Uint16 *d = g_screen_fbp;
for (sw *= Bpp; sh > 0; d += dpitch, s += spitch, sh--)
memcpy(d, s, sw);
}
- // else TODO
+ else
+ not_supported();
return 0;
}
{
trace("%p, %p, %04x", dst, dstrect, color);
- if (dst->format->BytesPerPixel == 2) {
- err("SDL_FillRect TODO");
+ if (dst->format->BytesPerPixel != 1) {
+ not_supported();
return -1;
}
else
} __attribute__((packed)) bmp;
SDL_Surface *ret = NULL;
int data_size, read_size;
- uint8_t *tmp_buf;
+ uint8_t *tmp_buf = NULL;
int i, bytespp;
FILE *f;
return 0;
}
-DECLSPEC SDL_Joystick * SDLCALL
-SDL_JoystickOpen(int device_index)
-{
- trace("%d", device_index);
- return NULL;
-}
-
-DECLSPEC int SDLCALL
-SDL_PollEvent(SDL_Event *event)
-{
- trace("%p", event);
- return 0;
-}
-
-DECLSPEC Uint8 * SDLCALL
-SDL_GetKeyState(int *numkeys)
-{
- trace("%p", numkeys);
-
- if (numkeys != NULL)
- *numkeys = ARRAY_SIZE(g_keystate);
- return g_keystate;
-}
-
DECLSPEC void SDLCALL
SDL_WM_SetCaption(const char *title, const char *icon)
{
--- /dev/null
+#include <strings.h>
+#include <SDL/SDL.h>
+#include <linux/input.h>
+
+#include "pmsdl.h"
+#include "common/input.h"
+
+static unsigned char g_keystate[SDLK_LAST];
+
+static short pmsdl_map[KEY_CNT] = {
+ [KEY_0] = SDLK_0,
+ [KEY_1] = SDLK_1,
+ [KEY_2] = SDLK_2,
+ [KEY_3] = SDLK_3,
+ [KEY_4] = SDLK_4,
+ [KEY_5] = SDLK_5,
+ [KEY_6] = SDLK_6,
+ [KEY_7] = SDLK_7,
+ [KEY_8] = SDLK_8,
+ [KEY_9] = SDLK_9,
+ [KEY_A] = SDLK_a,
+ [KEY_B] = SDLK_b,
+ [KEY_C] = SDLK_c,
+ [KEY_D] = SDLK_d,
+ [KEY_E] = SDLK_e,
+ [KEY_F] = SDLK_f,
+ [KEY_G] = SDLK_g,
+ [KEY_H] = SDLK_h,
+ [KEY_I] = SDLK_i,
+ [KEY_J] = SDLK_j,
+ [KEY_K] = SDLK_k,
+ [KEY_L] = SDLK_l,
+ [KEY_M] = SDLK_m,
+ [KEY_N] = SDLK_n,
+ [KEY_O] = SDLK_o,
+ [KEY_P] = SDLK_p,
+ [KEY_Q] = SDLK_q,
+ [KEY_R] = SDLK_r,
+ [KEY_S] = SDLK_s,
+ [KEY_T] = SDLK_t,
+ [KEY_U] = SDLK_u,
+ [KEY_V] = SDLK_v,
+ [KEY_W] = SDLK_w,
+ [KEY_X] = SDLK_x,
+ [KEY_Y] = SDLK_y,
+ [KEY_Z] = SDLK_z,
+ [KEY_SPACE] = SDLK_SPACE,
+ [KEY_BACKSPACE] = SDLK_BACKSPACE,
+ [KEY_FN] = SDLK_MODE,
+ [KEY_DOT] = SDLK_PERIOD,
+ [KEY_ENTER] = SDLK_RETURN,
+ [KEY_LEFTSHIFT] = SDLK_LSHIFT,
+ [KEY_COMMA] = SDLK_COMMA,
+// [KEY_BRIGHTNESSUP] =
+// [KEY_BRIGHTNESSDOWN] =
+// [KEY_GRAVE] =
+ [KEY_TAB] = SDLK_TAB,
+ [KEY_INSERT] = SDLK_INSERT,
+ [KEY_EQUAL] = SDLK_EQUALS,
+ [KEY_KPPLUS] = SDLK_KP_PLUS,
+ [KEY_BACKSLASH] = SDLK_BACKSLASH,
+ [KEY_RIGHTBRACE]= SDLK_RIGHTBRACKET,
+ [KEY_KPMINUS] = SDLK_KP_MINUS,
+ [KEY_QUESTION] = SDLK_QUESTION,
+ [KEY_LEFTBRACE] = SDLK_LEFTBRACKET,
+ [KEY_SLASH] = SDLK_SLASH,
+// [KEY_YEN] =
+ [KEY_APOSTROPHE]= SDLK_QUOTE,
+ [KEY_ESC] = SDLK_ESCAPE,
+ [KEY_CAPSLOCK] = SDLK_CAPSLOCK,
+ [KEY_SEMICOLON] = SDLK_SEMICOLON,
+ [KEY_F1] = SDLK_F1,
+ [KEY_F2] = SDLK_F2,
+ [KEY_F3] = SDLK_F3,
+ [KEY_F4] = SDLK_F4,
+ [KEY_F5] = SDLK_F5,
+ [KEY_F6] = SDLK_F6,
+ [KEY_F7] = SDLK_F7,
+ [KEY_F8] = SDLK_F8,
+ [KEY_F9] = SDLK_F9,
+ [KEY_F10] = KEY_F10,
+ [KEY_F11] = KEY_F11,
+ [KEY_F12] = KEY_F12,
+ [KEY_F13] = KEY_F13, /* apostrophe, differs from Fn-A? */
+ [KEY_F14] = KEY_F14, /* pipe/bar */
+ [KEY_F15] = KEY_F15, /* dash */
+ [KEY_F16] = SDLK_HASH, /* # (pound/hash) */
+ [KEY_F17] = SDLK_EXCLAIM, /* ! */
+// [KEY_F18] = /* £ (pound) */
+ [KEY_F19] = SDLK_QUOTEDBL,/* " */
+ [KEY_F20] = SDLK_AT, /* @ */
+ [KEY_F21] = SDLK_SEMICOLON,/* : */
+// [KEY_F22] =
+// [KEY_F23] =
+
+ [KEY_UP] = SDLK_UP,
+ [KEY_DOWN] = SDLK_DOWN,
+ [KEY_LEFT] = SDLK_LEFT,
+ [KEY_RIGHT] = SDLK_RIGHT,
+ [KEY_HOME] = SDLK_HOME,
+ [KEY_END] = SDLK_END,
+ [KEY_PAGEUP] = SDLK_PAGEUP,
+ [KEY_PAGEDOWN] = SDLK_PAGEDOWN,
+ [KEY_LEFTALT] = SDLK_LALT,
+ [KEY_LEFTCTRL] = SDLK_LCTRL,
+// [KEY_MENU] =
+ [KEY_RIGHTSHIFT]= SDLK_RSHIFT,
+ [KEY_RIGHTCTRL] = SDLK_RCTRL,
+};
+
+#define DNKEY(x) [SDLK_##x] = #x
+static const char *sdl_keynames[SDLK_LAST] = {
+ DNKEY(BACKSPACE),
+ DNKEY(TAB),
+ DNKEY(RETURN),
+ DNKEY(ESCAPE),
+ DNKEY(SPACE),
+ DNKEY(EXCLAIM),
+ DNKEY(QUOTEDBL),
+ DNKEY(HASH),
+ DNKEY(DOLLAR),
+ DNKEY(AMPERSAND),
+ DNKEY(QUOTE),
+ DNKEY(LEFTPAREN),
+ DNKEY(RIGHTPAREN),
+ DNKEY(ASTERISK),
+ DNKEY(PLUS),
+ DNKEY(COMMA),
+ DNKEY(MINUS),
+ DNKEY(PERIOD),
+ DNKEY(SLASH),
+ DNKEY(0),
+ DNKEY(1),
+ DNKEY(2),
+ DNKEY(3),
+ DNKEY(4),
+ DNKEY(5),
+ DNKEY(6),
+ DNKEY(7),
+ DNKEY(8),
+ DNKEY(9),
+ DNKEY(COLON),
+ DNKEY(SEMICOLON),
+ DNKEY(LESS),
+ DNKEY(EQUALS),
+ DNKEY(GREATER),
+ DNKEY(QUESTION),
+ DNKEY(AT),
+ DNKEY(LEFTBRACKET),
+ DNKEY(BACKSLASH),
+ DNKEY(RIGHTBRACKET),
+ DNKEY(CARET),
+ DNKEY(UNDERSCORE),
+ DNKEY(BACKQUOTE),
+ DNKEY(a),
+ DNKEY(b),
+ DNKEY(c),
+ DNKEY(d),
+ DNKEY(e),
+ DNKEY(f),
+ DNKEY(g),
+ DNKEY(h),
+ DNKEY(i),
+ DNKEY(j),
+ DNKEY(k),
+ DNKEY(l),
+ DNKEY(m),
+ DNKEY(n),
+ DNKEY(o),
+ DNKEY(p),
+ DNKEY(q),
+ DNKEY(r),
+ DNKEY(s),
+ DNKEY(t),
+ DNKEY(u),
+ DNKEY(v),
+ DNKEY(w),
+ DNKEY(x),
+ DNKEY(y),
+ DNKEY(z),
+ DNKEY(DELETE),
+ DNKEY(WORLD_0),
+ DNKEY(WORLD_1),
+ DNKEY(WORLD_2),
+ DNKEY(WORLD_3),
+ DNKEY(WORLD_4),
+ DNKEY(WORLD_5),
+ DNKEY(WORLD_6),
+ DNKEY(WORLD_7),
+ DNKEY(WORLD_8),
+ DNKEY(WORLD_9),
+ DNKEY(WORLD_10),
+ DNKEY(WORLD_11),
+ DNKEY(WORLD_12),
+ DNKEY(WORLD_13),
+ DNKEY(WORLD_14),
+ DNKEY(WORLD_15),
+ DNKEY(WORLD_16),
+ DNKEY(WORLD_17),
+ DNKEY(WORLD_18),
+ DNKEY(WORLD_19),
+ DNKEY(WORLD_20),
+ DNKEY(WORLD_21),
+ DNKEY(WORLD_22),
+ DNKEY(WORLD_23),
+ DNKEY(WORLD_24),
+ DNKEY(WORLD_25),
+ DNKEY(WORLD_26),
+ DNKEY(WORLD_27),
+ DNKEY(WORLD_28),
+ DNKEY(WORLD_29),
+ DNKEY(WORLD_30),
+ DNKEY(WORLD_31),
+ DNKEY(WORLD_32),
+ DNKEY(WORLD_33),
+ DNKEY(WORLD_34),
+ DNKEY(WORLD_35),
+ DNKEY(WORLD_36),
+ DNKEY(WORLD_37),
+ DNKEY(WORLD_38),
+ DNKEY(WORLD_39),
+ DNKEY(WORLD_40),
+ DNKEY(WORLD_41),
+ DNKEY(WORLD_42),
+ DNKEY(WORLD_43),
+ DNKEY(WORLD_44),
+ DNKEY(WORLD_45),
+ DNKEY(WORLD_46),
+ DNKEY(WORLD_47),
+ DNKEY(WORLD_48),
+ DNKEY(WORLD_49),
+ DNKEY(WORLD_50),
+ DNKEY(WORLD_51),
+ DNKEY(WORLD_52),
+ DNKEY(WORLD_53),
+ DNKEY(WORLD_54),
+ DNKEY(WORLD_55),
+ DNKEY(WORLD_56),
+ DNKEY(WORLD_57),
+ DNKEY(WORLD_58),
+ DNKEY(WORLD_59),
+ DNKEY(WORLD_60),
+ DNKEY(WORLD_61),
+ DNKEY(WORLD_62),
+ DNKEY(WORLD_63),
+ DNKEY(WORLD_64),
+ DNKEY(WORLD_65),
+ DNKEY(WORLD_66),
+ DNKEY(WORLD_67),
+ DNKEY(WORLD_68),
+ DNKEY(WORLD_69),
+ DNKEY(WORLD_70),
+ DNKEY(WORLD_71),
+ DNKEY(WORLD_72),
+ DNKEY(WORLD_73),
+ DNKEY(WORLD_74),
+ DNKEY(WORLD_75),
+ DNKEY(WORLD_76),
+ DNKEY(WORLD_77),
+ DNKEY(WORLD_78),
+ DNKEY(WORLD_79),
+ DNKEY(WORLD_80),
+ DNKEY(WORLD_81),
+ DNKEY(WORLD_82),
+ DNKEY(WORLD_83),
+ DNKEY(WORLD_84),
+ DNKEY(WORLD_85),
+ DNKEY(WORLD_86),
+ DNKEY(WORLD_87),
+ DNKEY(WORLD_88),
+ DNKEY(WORLD_89),
+ DNKEY(WORLD_90),
+ DNKEY(WORLD_91),
+ DNKEY(WORLD_92),
+ DNKEY(WORLD_93),
+ DNKEY(WORLD_94),
+ DNKEY(WORLD_95),
+ DNKEY(KP0),
+ DNKEY(KP1),
+ DNKEY(KP2),
+ DNKEY(KP3),
+ DNKEY(KP4),
+ DNKEY(KP5),
+ DNKEY(KP6),
+ DNKEY(KP7),
+ DNKEY(KP8),
+ DNKEY(KP9),
+ DNKEY(KP_PERIOD),
+ DNKEY(KP_DIVIDE),
+ DNKEY(KP_MULTIPLY),
+ DNKEY(KP_MINUS),
+ DNKEY(KP_PLUS),
+ DNKEY(KP_ENTER),
+ DNKEY(KP_EQUALS),
+ DNKEY(UP),
+ DNKEY(DOWN),
+ DNKEY(RIGHT),
+ DNKEY(LEFT),
+ DNKEY(INSERT),
+ DNKEY(HOME),
+ DNKEY(END),
+ DNKEY(PAGEUP),
+ DNKEY(PAGEDOWN),
+ DNKEY(F1),
+ DNKEY(F2),
+ DNKEY(F3),
+ DNKEY(F4),
+ DNKEY(F5),
+ DNKEY(F6),
+ DNKEY(F7),
+ DNKEY(F8),
+ DNKEY(F9),
+ DNKEY(F10),
+ DNKEY(F11),
+ DNKEY(F12),
+ DNKEY(F13),
+ DNKEY(F14),
+ DNKEY(F15),
+ DNKEY(NUMLOCK),
+ DNKEY(CAPSLOCK),
+ DNKEY(SCROLLOCK),
+ DNKEY(RSHIFT),
+ DNKEY(LSHIFT),
+ DNKEY(RCTRL),
+ DNKEY(LCTRL),
+ DNKEY(RALT),
+ DNKEY(LALT),
+ DNKEY(RMETA),
+ DNKEY(LMETA),
+ DNKEY(LSUPER),
+ DNKEY(RSUPER),
+ DNKEY(MODE),
+ DNKEY(COMPOSE),
+};
+
+void pmsdl_input_bind(const char *kname, const char *sdlname)
+{
+ int i, kc;
+
+ kc = in_get_key_code(-1, kname);
+ if (kc < 0) {
+ err("can't resolve key '%s'", kname);
+ return;
+ }
+
+ if (sdlname == NULL || strncasecmp(sdlname, "SDLK_", 5) != 0)
+ goto bad_sdlkey;
+
+ for (i = 0; i < SDLK_LAST; i++) {
+ if (sdl_keynames[i] == NULL)
+ continue;
+ if (strcasecmp(sdl_keynames[i], sdlname + 5) == 0)
+ break;
+ }
+
+ if (i >= SDLK_LAST)
+ goto bad_sdlkey;
+
+ pmsdl_map[kc] = i;
+ return;
+
+bad_sdlkey:
+ err("can't resolve SDL key '%s'", sdlname);
+}
+
+void pmsdl_input_init(void)
+{
+ in_init();
+ in_probe();
+}
+
+static int do_event(SDL_Event *event, int timeout)
+{
+ int key, is_down;
+
+ while (1) {
+ int kc;
+
+ is_down = 0;
+ kc = in_update_keycode(NULL, &is_down, timeout);
+ if (kc < 0 || kc > KEY_MAX)
+ return 0;
+
+ key = pmsdl_map[kc];
+ if (key != 0)
+ break;
+ }
+
+ g_keystate[key] = is_down;
+
+ if (event == NULL)
+ return 1; // FIXME: ..but the event is lost
+
+ memset(event, 0, sizeof(event->key));
+ event->type = is_down ? SDL_KEYDOWN : SDL_KEYUP;
+ // event->key.which =
+ event->key.state = is_down ? SDL_PRESSED : SDL_RELEASED;
+ event->key.keysym.sym = key;
+ // event->key.keysym.mod
+
+ return 1;
+}
+
+/* SDL */
+DECLSPEC int SDLCALL
+SDL_WaitEvent(SDL_Event *event)
+{
+ trace("%p", event);
+
+ return do_event(event, -1);
+}
+
+DECLSPEC int SDLCALL
+SDL_PollEvent(SDL_Event *event)
+{
+ trace("%p", event);
+
+ return do_event(event, 0);
+}
+
+DECLSPEC Uint8 * SDLCALL
+SDL_GetKeyState(int *numkeys)
+{
+ trace("%p", numkeys);
+
+ if (numkeys != NULL)
+ *numkeys = ARRAY_SIZE(g_keystate);
+ return g_keystate;
+}
+
+DECLSPEC char * SDLCALL
+SDL_GetKeyName(SDLKey key)
+{
+ trace("%d", key);
+
+ if ((unsigned int)key < ARRAY_SIZE(sdl_keynames))
+ return (char *)sdl_keynames[key];
+ else
+ return "";
+}
+
+DECLSPEC int SDLCALL
+SDL_EnableUNICODE(int enable)
+{
+ trace("%d", enable);
+
+ if (enable > 0)
+ not_supported();
+
+ return 0;
+}
+
+DECLSPEC int SDLCALL
+SDL_EnableKeyRepeat(int delay, int interval)
+{
+ trace("%d, %d", delay, interval);
+
+ if (delay)
+ not_supported();
+ return 0;
+}
+
+DECLSPEC void SDLCALL
+SDL_GetKeyRepeat(int *delay, int *interval)
+{
+ trace("%p, %p", delay, interval);
+
+ if (delay)
+ *delay = 0;
+ if (interval)
+ *interval = 0;
+}
+
+DECLSPEC SDLMod SDLCALL
+SDL_GetModState(void)
+{
+ static const short syms[] = { SDLK_LSHIFT, SDLK_RSHIFT, SDLK_LCTRL, SDLK_RCTRL, SDLK_LALT,
+ SDLK_RALT, SDLK_LMETA, SDLK_RMETA, SDLK_NUMLOCK, SDLK_CAPSLOCK, SDLK_MODE };
+ static const short mods[] = { KMOD_LSHIFT, KMOD_RSHIFT, KMOD_LCTRL, KMOD_RCTRL, KMOD_LALT,
+ KMOD_RALT, KMOD_LMETA, KMOD_RMETA, KMOD_NUM, KMOD_CAPS, KMOD_MODE };
+ SDLMod ret = KMOD_NONE;
+ int i;
+
+ trace("");
+
+ for (i = 0; i < ARRAY_SIZE(syms); i++)
+ if (g_keystate[syms[i]])
+ ret |= mods[i];
+
+ return ret;
+}
+
+/* Joysticks */
+DECLSPEC int SDLCALL
+SDL_NumJoysticks(void)
+{
+ trace("");
+ return 0;
+}
+
+DECLSPEC SDL_Joystick * SDLCALL
+SDL_JoystickOpen(int device_index)
+{
+ trace("%d", device_index);
+ return NULL;
+}
+