10 #include "common/input.h"
11 #include "linux/fbdev.h"
12 #include "linux/oshide.h"
14 static SDL_Surface *g_screen;
15 static void *g_screen_fbp;
16 static Uint16 g_8bpp_pal[256];
17 static Uint32 g_start_ticks;
19 static inline int min(int v1, int v2)
21 return v1 < v2 ? v1 : v2;
24 static SDL_Surface *alloc_surface(int w, int h, int bpp)
26 // SDL has some pointer overuse, every surface has a format,
27 // why make format accessible through pointer?
33 ret = calloc(1, sizeof(*ret));
37 ret->s.format = &ret->f;
38 ret->f.BitsPerPixel = bpp;
39 ret->f.BytesPerPixel = (bpp + 7) / 8;
43 ret->s.pitch = w * ret->f.BytesPerPixel;
49 static char *sskip(char *p)
51 while (*p && isspace(*p))
56 static char *nsskip(char *p)
58 while (*p && !isspace(*p))
63 static int check_token(const char *p, const char *token)
65 int tlen = strlen(token);
66 return strncasecmp(p, token, tlen) == 0 && isspace(p[tlen]);
69 static void do_config(void)
74 f = fopen("pmsdl.cfg", "r");
79 char *p, *line = fgets(buff, sizeof(buff), f);
82 p = line = sskip(line);
86 if (check_token(p, "bind")) {
87 char *key, *key_end, *sdlkey, *sdlkey_end;
89 key_end = nsskip(key);
93 sdlkey = sskip(p + 1);
94 sdlkey_end = nsskip(sdlkey);
95 p = sskip(sdlkey_end);
96 if (*key == 0 || *sdlkey == 0 || *p != 0)
98 *key_end = *sdlkey_end = 0;
100 pmsdl_input_bind(key, sdlkey);
105 err("config: failed to parse: %s", line);
111 SDL_Init(Uint32 flags)
113 trace("%08x", flags);
115 if (g_start_ticks == 0) {
122 g_start_ticks = SDL_GetTicks();
127 DECLSPEC void SDLCALL
132 if (g_start_ticks != 0) {
139 SDL_InitSubSystem(Uint32 flags)
141 trace("%08x", flags);
145 DECLSPEC void SDLCALL
146 SDL_QuitSubSystem(Uint32 flags)
148 trace("%08x", flags);
151 DECLSPEC Uint32 SDLCALL
157 gettimeofday(&tv, NULL);
158 ret = tv.tv_sec * 1000;
159 ret += tv.tv_usec * 1048 >> 20;
161 ret -= g_start_ticks;
162 dbg(" SDL_GetTicks %d", ret);
166 DECLSPEC SDL_Surface * SDLCALL
167 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
169 struct vout_fbdev *fbdev;
171 trace("%d, %d, %d, %08x", width, height, bpp, flags);
176 if (bpp != 8 && bpp != 16) {
177 err("unsupported bpp: %d\n", bpp);
181 // XXX: destroy old g_screen?
183 g_screen = alloc_surface(width, height, bpp);
184 if (g_screen == NULL)
187 fbdev = vout_fbdev_init("/dev/fb0", &width, &height, 0);
189 goto fail_fbdev_init;
191 g_screen_fbp = vout_fbdev_flip(fbdev);
193 g_screen->pixels = g_screen_fbp;
195 // we have to fake this for now..
196 g_screen->pixels = calloc(g_screen->pitch * height, 1);
198 if (g_screen->pixels == NULL) {
202 g_screen->hwdata = (void *)fbdev;
204 dbg("returning %p", g_screen);
208 vout_fbdev_finish(fbdev);
216 SDL_Flip(SDL_Surface *screen)
218 struct vout_fbdev *fbdev;
222 if (screen != g_screen) {
223 err("flip not on screen surface?");
227 if (screen->format->BitsPerPixel == 8) {
228 int l = screen->pitch * screen->h;
230 do_clut(g_screen_fbp, screen->pixels, g_8bpp_pal, l);
232 Uint16 *d = g_screen_fbp;
233 Uint8 *s = screen->pixels;
235 // XXX: perhaps optimize this sh*t
236 for (; l > 0; d++, s++, l--)
241 fbdev = (void *)screen->hwdata;
242 g_screen_fbp = vout_fbdev_flip(fbdev);
244 if (screen->format->BitsPerPixel != 8)
245 screen->pixels = g_screen_fbp;
250 static int do_rect_clip(const SDL_Surface *s, SDL_Rect *r)
252 int x = r->x, y = r->y, w = r->w, h = r->h;
277 r->x = x; r->y = y; r->w = w; r->h = h;
278 return (w > 0 && h > 0) ? 0 : -1;
282 SDL_UpperBlit(SDL_Surface *src, SDL_Rect *srcrect,
283 SDL_Surface *dst, SDL_Rect *dstrect)
285 int sx = 0, sy = 0, sw, sh;
287 SDL_Rect tmprect = { 0, };
289 trace("%p, %p, %p, %p", src, srcrect, dst, dstrect);
291 if (src == NULL || dst == NULL)
294 if (srcrect != NULL) {
295 // XXX: dst pos may need to be adjusted in some corner cases
296 if (do_rect_clip(src, srcrect) < 0)
310 // SDL just uses source w and h
313 if (do_rect_clip(dst, dstrect) < 0)
320 dbg("(%d %d %d %d) -> (%d %d %d %d)", sx, sy, sw, sh, dx, dy, sw, sh);
322 if (src->format->BitsPerPixel == dst->format->BitsPerPixel) {
323 int Bpp = src->format->BytesPerPixel;
324 int dpitch = dst->pitch;
325 int spitch = src->pitch;
326 Uint8 *d = (Uint8 *)dst->pixels + dpitch * dy + dx * Bpp;
327 Uint8 *s = (Uint8 *)src->pixels + spitch * sy + sx * Bpp;
329 for (sw *= Bpp; sh > 0; d += dpitch, s += spitch, sh--)
338 DECLSPEC SDL_Surface * SDLCALL
339 SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth,
340 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
344 trace("%08x, %d, %d, %d, %04x, %04x, %04x, %04x",
345 flags, width, height, depth, Rmask, Gmask, Bmask, Amask);
347 ret = alloc_surface(width, height, depth);
351 ret->pixels = calloc(ret->pitch * height, 1);
352 if (ret->pixels == NULL)
355 dbg("returning %p", ret);
364 SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors)
368 trace("%p, %p, %d, %d", surface, colors, firstcolor, ncolors);
370 if (surface != g_screen)
373 to = min(ARRAY_SIZE(g_8bpp_pal), firstcolor + ncolors);
374 for (i = firstcolor; i < to; i++) {
375 SDL_Color *c = &colors[i - firstcolor];
376 int r = c->r, g = c->g, b = c->b;
377 // noiz2sa gets a good deal darker that real SDL,
378 // don't know what's going on there
380 if (r < 0xf8 && (r & 7) > 3) r += 8;
381 if (g < 0xfc && (g & 3) > 1) g += 4;
382 if (b < 0xf8 && (b & 7) > 3) b += 8;
384 g_8bpp_pal[i] = ((r << 8) & 0xf800) | ((g << 3) & 0x07e0) | (b >> 3);
385 // g_8bpp_pal[i] += 0x0821;
392 SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
394 trace("%p, %p, %04x", dst, dstrect, color);
396 if (dst->format->BytesPerPixel != 1) {
401 memset(dst->pixels, color, dst->pitch * dst->h);
407 DECLSPEC SDL_Surface * SDLCALL
408 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch,
409 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
414 DECLSPEC SDL_RWops * SDLCALL
415 SDL_RWFromFile(const char *file, const char *mode)
420 trace("%s, %s", file, mode);
422 f = fopen(file, mode);
426 ret = calloc(1, sizeof(*ret));
431 ret->hidden.stdio.fp = f;
436 DECLSPEC void SDLCALL
437 SDL_FreeRW(SDL_RWops *area)
439 if (area->hidden.stdio.fp) {
440 fclose(area->hidden.stdio.fp);
441 area->hidden.stdio.fp = NULL;
446 DECLSPEC SDL_Surface * SDLCALL
447 SDL_LoadBMP_RW(SDL_RWops *src, int freesrc)
450 unsigned char magic[2];
460 uint32_t compress_type;
466 } __attribute__((packed)) bmp;
467 SDL_Surface *ret = NULL;
468 int data_size, read_size;
469 uint8_t *tmp_buf = NULL;
473 trace("%p, %d", src, freesrc);
475 f = src->hidden.stdio.fp;
479 if (fread(&bmp, 1, sizeof(bmp), f) != sizeof(bmp)) {
480 err("bmp read error");
484 if (bmp.magic[0] != 'B' || bmp.magic[1] != 'M' || bmp.header_sz != 40) {
485 err("unhandled BMP format, sz=%d", bmp.header_sz);
489 if ((unsigned)bmp.width > 0xffff || (unsigned)bmp.height > 0xffff) {
490 err("BMP size %dx%d out of range", bmp.width, bmp.height);
494 if (bmp.bitspp != 4) {
495 err("BMP unhandled bpp: %d", bmp.bitspp);
499 bytespp = bmp.bitspp < 8 ? 1 : (bmp.bitspp + 7) / 8;
500 data_size = bmp.width * bmp.height * bytespp;
501 tmp_buf = malloc(data_size);
505 if (fseek(f, bmp.bmp_offset, SEEK_SET) != 0) {
506 err("BMP seek error");
510 read_size = bmp.width * bmp.bitspp / 8;
511 for (i = bmp.height - 1; i > 0; i--) {
512 if (fread((char *)tmp_buf + i * read_size, 1, read_size, f) != read_size) {
513 err("BMP read error");
518 if (bmp.bitspp == 4) {
519 // just convert to 8bpp now
520 int c = bmp.width * bmp.height / 2;
521 uint8_t *p = tmp_buf;
522 for (i = c - 1; i >= 0; i--) {
523 p[i * 2 + 1] = p[i] & 0xf;
524 p[i * 2] = p[i] >> 4;
528 ret = alloc_surface(bmp.width, bmp.height, 8);
532 ret->pixels = tmp_buf;
544 DECLSPEC SDL_Surface * SDLCALL
545 SDL_ConvertSurface(SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags)
550 trace("%p, %p, %08x", src, fmt, flags);
552 if (src->format->BitsPerPixel != fmt->BitsPerPixel) {
553 err("convert: not implemented");
557 data = malloc(src->pitch * src->h);
560 memcpy(data, src->pixels, src->pitch * src->h);
562 ret = alloc_surface(src->w, src->h, fmt->BitsPerPixel);
572 SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key)
574 trace("%p, %08x, %04x", surface, flag, key);
578 DECLSPEC void SDLCALL
579 SDL_WM_SetCaption(const char *title, const char *icon)
581 trace("%s, %s", title, icon);
585 SDL_ShowCursor(int toggle)
591 DECLSPEC char * SDLCALL