/*
* PicoDrive
* (C) notaz, 2013
+ * (C) irixxxx, 2020-2024
*
* This work is licensed under the terms of MAME license.
* See COPYING file in the top-level directory.
#include <stdio.h>
#include "../libpicofe/input.h"
+#include "../libpicofe/plat.h"
#include "../libpicofe/plat_sdl.h"
#include "../libpicofe/in_sdl.h"
#include "../libpicofe/gl.h"
#include "emu.h"
#include "menu_pico.h"
#include "input_pico.h"
+#include "plat_sdl.h"
#include "version.h"
-#include <pico/pico.h>
+#include <pico/pico_int.h>
static void *shadow_fb;
+static int shadow_size;
+static struct area { int w, h; } area;
-const struct in_default_bind in_sdl_defbinds[] __attribute__((weak)) = {
- { SDLK_UP, IN_BINDTYPE_PLAYER12, GBTN_UP },
- { SDLK_DOWN, IN_BINDTYPE_PLAYER12, GBTN_DOWN },
- { SDLK_LEFT, IN_BINDTYPE_PLAYER12, GBTN_LEFT },
- { SDLK_RIGHT, IN_BINDTYPE_PLAYER12, GBTN_RIGHT },
- { SDLK_z, IN_BINDTYPE_PLAYER12, GBTN_A },
- { SDLK_x, IN_BINDTYPE_PLAYER12, GBTN_B },
- { SDLK_c, IN_BINDTYPE_PLAYER12, GBTN_C },
- { SDLK_a, IN_BINDTYPE_PLAYER12, GBTN_X },
- { SDLK_s, IN_BINDTYPE_PLAYER12, GBTN_Y },
- { SDLK_d, IN_BINDTYPE_PLAYER12, GBTN_Z },
- { SDLK_RETURN, IN_BINDTYPE_PLAYER12, GBTN_START },
- { SDLK_f, IN_BINDTYPE_PLAYER12, GBTN_MODE },
- { SDLK_ESCAPE, IN_BINDTYPE_EMU, PEVB_MENU },
- { SDLK_TAB, IN_BINDTYPE_EMU, PEVB_RESET },
- { SDLK_F1, IN_BINDTYPE_EMU, PEVB_STATE_SAVE },
- { SDLK_F2, IN_BINDTYPE_EMU, PEVB_STATE_LOAD },
- { SDLK_F3, IN_BINDTYPE_EMU, PEVB_SSLOT_PREV },
- { SDLK_F4, IN_BINDTYPE_EMU, PEVB_SSLOT_NEXT },
- { SDLK_F5, IN_BINDTYPE_EMU, PEVB_SWITCH_RND },
- { SDLK_F6, IN_BINDTYPE_EMU, PEVB_PICO_PPREV },
- { SDLK_F7, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT },
- { SDLK_F8, IN_BINDTYPE_EMU, PEVB_PICO_SWINP },
- { SDLK_BACKSPACE, IN_BINDTYPE_EMU, PEVB_FF },
- { 0, 0, 0 }
-};
-
-const struct menu_keymap in_sdl_key_map[] __attribute__((weak)) =
+static struct in_pdata in_sdl_platform_data;
+
+static int hide_cursor;
+
+static int sound_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 53000, -1 };
+struct plat_target plat_target = { .sound_rates = sound_rates };
+
+#if defined __MIYOO__
+const char *plat_device = "miyoo";
+#elif defined __GCW0__
+const char *plat_device = "gcw0";
+#elif defined __RETROFW__
+const char *plat_device = "retrofw";
+#elif defined __DINGUX__
+const char *plat_device = "dingux";
+#else
+const char *plat_device = "";
+#endif
+
+int plat_parse_arg(int argc, char *argv[], int *x)
{
- { SDLK_UP, PBTN_UP },
- { SDLK_DOWN, PBTN_DOWN },
- { SDLK_LEFT, PBTN_LEFT },
- { SDLK_RIGHT, PBTN_RIGHT },
- { SDLK_RETURN, PBTN_MOK },
- { SDLK_ESCAPE, PBTN_MBACK },
- { SDLK_SEMICOLON, PBTN_MA2 },
- { SDLK_QUOTE, PBTN_MA3 },
- { SDLK_LEFTBRACKET, PBTN_L },
- { SDLK_RIGHTBRACKET, PBTN_R },
-};
-
-const struct menu_keymap in_sdl_joy_map[] __attribute__((weak)) =
+#if defined __OPENDINGUX__
+ if (*plat_device == '\0' && strcasecmp(argv[*x], "-device") == 0) {
+ plat_device = argv[++(*x)];
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+void plat_early_init(void)
{
- { SDLK_UP, PBTN_UP },
- { SDLK_DOWN, PBTN_DOWN },
- { SDLK_LEFT, PBTN_LEFT },
- { SDLK_RIGHT, PBTN_RIGHT },
- /* joystick */
- { SDLK_WORLD_0, PBTN_MOK },
- { SDLK_WORLD_1, PBTN_MBACK },
- { SDLK_WORLD_2, PBTN_MA2 },
- { SDLK_WORLD_3, PBTN_MA3 },
-};
-
-extern const char * const in_sdl_key_names[] __attribute__((weak));
-
-static const struct in_pdata in_sdl_platform_data = {
- .defbinds = in_sdl_defbinds,
- .key_map = in_sdl_key_map,
- .kmap_size = sizeof(in_sdl_key_map) / sizeof(in_sdl_key_map[0]),
- .joy_map = in_sdl_joy_map,
- .jmap_size = sizeof(in_sdl_joy_map) / sizeof(in_sdl_joy_map[0]),
- .key_names = in_sdl_key_names,
-};
+}
+
+int plat_target_init(void)
+{
+#if defined __ODBETA__
+ if (*plat_device == '\0') {
+ /* ODbeta should always have a device tree, get the model info from there */
+ FILE *f = fopen("/proc/device-tree/compatible", "r");
+ if (f) {
+ char buf[10];
+ int c = fread(buf, 1, sizeof(buf), f);
+ if (strncmp(buf, "gcw,", 4) == 0)
+ plat_device = "gcw0";
+ }
+ }
+#endif
+ return 0;
+}
+
+void plat_target_finish(void)
+{
+}
/* YUV stuff */
static int yuv_ry[32], yuv_gy[32], yuv_by[32];
static unsigned char yuv_u[32 * 2], yuv_v[32 * 2];
+static unsigned char yuv_y[256];
+static struct uyvy { uint32_t y:8; uint32_t vyu:24; } yuv_uyvy[65536];
void bgr_to_uyvy_init(void)
{
- int i, v;
-
- /* init yuv converter:
- y0 = (int)((0.299f * r0) + (0.587f * g0) + (0.114f * b0));
- y1 = (int)((0.299f * r1) + (0.587f * g1) + (0.114f * b1));
- u = (int)(8 * 0.565f * (b0 - y0)) + 128;
- v = (int)(8 * 0.713f * (r0 - y0)) + 128;
- */
- for (i = 0; i < 32; i++) {
- yuv_ry[i] = (int)(0.299f * i * 65536.0f + 0.5f);
- yuv_gy[i] = (int)(0.587f * i * 65536.0f + 0.5f);
- yuv_by[i] = (int)(0.114f * i * 65536.0f + 0.5f);
- }
- for (i = -32; i < 32; i++) {
- v = (int)(8 * 0.565f * i) + 128;
- if (v < 0)
- v = 0;
- if (v > 255)
- v = 255;
- yuv_u[i + 32] = v;
- v = (int)(8 * 0.713f * i) + 128;
- if (v < 0)
- v = 0;
- if (v > 255)
- v = 255;
- yuv_v[i + 32] = v;
- }
+ int i, v;
+
+ /* init yuv converter:
+ y0 = (int)((0.299f * r0) + (0.587f * g0) + (0.114f * b0));
+ y1 = (int)((0.299f * r1) + (0.587f * g1) + (0.114f * b1));
+ u = (int)(8 * 0.565f * (b0 - y0)) + 128;
+ v = (int)(8 * 0.713f * (r0 - y0)) + 128;
+ */
+ for (i = 0; i < 32; i++) {
+ yuv_ry[i] = (int)(0.299f * i * 65536.0f + 0.5f);
+ yuv_gy[i] = (int)(0.587f * i * 65536.0f + 0.5f);
+ yuv_by[i] = (int)(0.114f * i * 65536.0f + 0.5f);
+ }
+ for (i = -32; i < 32; i++) {
+ v = (int)(8 * 0.565f * i) + 128;
+ if (v < 0)
+ v = 0;
+ if (v > 255)
+ v = 255;
+ yuv_u[i + 32] = v;
+ v = (int)(8 * 0.713f * i) + 128;
+ if (v < 0)
+ v = 0;
+ if (v > 255)
+ v = 255;
+ yuv_v[i + 32] = v;
+ }
+ // valid Y range seems to be 16..235
+ for (i = 0; i < 256; i++) {
+ yuv_y[i] = 16 + 219 * i / 32;
+ }
+ // everything combined into one large array for speed
+ for (i = 0; i < 65536; i++) {
+ int r = (i >> 11) & 0x1f, g = (i >> 6) & 0x1f, b = (i >> 0) & 0x1f;
+ int y = (yuv_ry[r] + yuv_gy[g] + yuv_by[b]) >> 16;
+ yuv_uyvy[i].y = yuv_y[y];
+#if CPU_IS_LE
+ yuv_uyvy[i].vyu = (yuv_v[r-y + 32] << 16) | (yuv_y[y] << 8) | yuv_u[b-y + 32];
+#else
+ yuv_uyvy[i].vyu = (yuv_v[b-y + 32] << 16) | (yuv_y[y] << 8) | yuv_u[r-y + 32];
+#endif
+ }
+}
+
+void rgb565_to_uyvy(void *d, const void *s, int w, int h, int pitch, int dpitch, int x2)
+{
+ uint32_t *dst = d;
+ const uint16_t *src = s;
+ int i;
+
+ if (x2) while (h--) {
+ for (i = w; i >= 4; src += 4, dst += 4, i -= 4)
+ {
+ struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
+ struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
+#if CPU_IS_LE
+ dst[0] = (uyvy0->y << 24) | uyvy0->vyu;
+ dst[1] = (uyvy1->y << 24) | uyvy1->vyu;
+ dst[2] = (uyvy2->y << 24) | uyvy2->vyu;
+ dst[3] = (uyvy3->y << 24) | uyvy3->vyu;
+#else
+ dst[0] = uyvy0->y | (uyvy0->vyu << 8);
+ dst[1] = uyvy1->y | (uyvy1->vyu << 8);
+ dst[2] = uyvy2->y | (uyvy2->vyu << 8);
+ dst[3] = uyvy3->y | (uyvy3->vyu << 8);
+#endif
+ }
+ src += pitch - (w-i);
+ dst += (dpitch - 2*(w-i))/2;
+ } else while (h--) {
+ for (i = w; i >= 4; src += 4, dst += 2, i -= 4)
+ {
+ struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
+ struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
+#if CPU_IS_LE
+ dst[0] = (uyvy1->y << 24) | uyvy0->vyu;
+ dst[1] = (uyvy3->y << 24) | uyvy2->vyu;
+#else
+ dst[0] = uyvy1->y | (uyvy0->vyu << 8);
+ dst[1] = uyvy3->y | (uyvy2->vyu << 8);
+#endif
+ }
+ src += pitch - (w-i);
+ dst += (dpitch - (w-i))/2;
+ }
+}
+
+void copy_intscale(void *dst, int w, int h, int pp, void *src, int sw, int sh, int spp)
+{
+ int xf = w / sw, yf = h / sh, f = xf < yf ? xf : yf;
+ int wf = f * sw, hf = f * sh;
+ int x = (w - wf)/2, y = (h - hf)/2;
+ uint16_t *p = (uint16_t *)dst;
+ uint16_t *q = (uint16_t *)src;
+
+ // copy 16bit image with scaling by an integer factor
+ int i, j, k, l;
+ p += y * pp + x;
+ for (i = 0; i < sh; i++) {
+ for (j = 0; j < sw; j++, q++)
+ for (l = 0; l < f; l++)
+ *p++ = *q;
+ p += pp - wf;
+ q += spp - sw;
+ for (k = 1; k < f; k++) {
+ memcpy(p, p-pp, wf*2);
+ p += pp;
+ }
+ }
}
-void rgb565_to_uyvy(void *d, const void *s, int pixels)
+static int clear_buf_cnt, clear_stat_cnt;
+
+static void resize_buffers(void)
{
- unsigned int *dst = d;
- const unsigned short *src = s;
- const unsigned char *yu = yuv_u + 32;
- const unsigned char *yv = yuv_v + 32;
- int r0, g0, b0, r1, g1, b1;
- int y0, y1, u, v;
-
- for (; pixels > 0; src += 2, dst++, pixels -= 2)
- {
- r0 = (src[0] >> 11) & 0x1f;
- g0 = (src[0] >> 6) & 0x1f;
- b0 = src[0] & 0x1f;
- r1 = (src[1] >> 11) & 0x1f;
- g1 = (src[1] >> 6) & 0x1f;
- b1 = src[1] & 0x1f;
- y0 = (yuv_ry[r0] + yuv_gy[g0] + yuv_by[b0]) >> 16;
- y1 = (yuv_ry[r1] + yuv_gy[g1] + yuv_by[b1]) >> 16;
- u = yu[b0 - y0];
- v = yv[r0 - y0];
- // valid Y range seems to be 16..235
- y0 = 16 + 219 * y0 / 31;
- y1 = 16 + 219 * y1 / 31;
-
- *dst = (y1 << 24) | (v << 16) | (y0 << 8) | u;
- }
+ // make sure the shadow buffers are big enough in case of resize
+ if (shadow_size < g_menuscreen_w * g_menuscreen_h * 2) {
+ shadow_size = g_menuscreen_w * g_menuscreen_h * 2;
+ shadow_fb = realloc(shadow_fb, shadow_size);
+ g_menubg_ptr = realloc(g_menubg_ptr, shadow_size);
+ }
+}
+
+void plat_video_set_size(int w, int h)
+{
+ if ((plat_sdl_overlay || plat_sdl_gl_active) && w <= 320 && h <= 240) {
+ // scale to the window, but mind aspect ratio (scaled to 4:3):
+ // w *= win_aspect / 4:3_aspect or h *= 4:3_aspect / win_aspect
+ if (g_menuscreen_w * 3/4 >= g_menuscreen_h)
+ w = (w * 3 * g_menuscreen_w/g_menuscreen_h)/4 & ~1;
+ else
+ h = (h * 4 * g_menuscreen_h/g_menuscreen_w)/3 & ~1;
+ }
+
+ if (area.w != w || area.h != h) {
+ area = (struct area) { w, h };
+
+ if (plat_sdl_overlay || plat_sdl_gl_active || !plat_sdl_is_windowed()) {
+ // create surface for overlays, or try using a hw scaler
+ if (plat_sdl_change_video_mode(w, h, 0) < 0) {
+ // failed, revert to original resolution
+ area = (struct area) { g_screen_width,g_screen_height };
+ plat_sdl_change_video_mode(g_screen_width, g_screen_height, 0);
+ }
+ }
+ if (plat_sdl_overlay || plat_sdl_gl_active) {
+ // use shadow buffer for overlays
+ g_screen_width = area.w;
+ g_screen_height = area.h;
+ g_screen_ppitch = area.w;
+ g_screen_ptr = shadow_fb;
+ } else if (plat_sdl_is_windowed() &&
+ (plat_sdl_screen->w >= 320*2 || plat_sdl_screen->h >= 240*2 ||
+ plat_sdl_screen->w < 320 || plat_sdl_screen->h < 240)) {
+ // shadow buffer for integer scaling
+ g_screen_width = 320;
+ g_screen_height = 240;
+ g_screen_ppitch = 320;
+ g_screen_ptr = shadow_fb;
+ } else {
+ // unscaled SDL window buffer can be used directly
+ g_screen_width = plat_sdl_screen->w;
+ g_screen_height = plat_sdl_screen->h;
+ g_screen_ppitch = plat_sdl_screen->pitch/2;
+ g_screen_ptr = plat_sdl_screen->pixels;
+ }
+ }
+}
+
+void plat_video_set_shadow(int w, int h)
+{
+ g_screen_width = w;
+ g_screen_height = h;
+ g_screen_ppitch = w;
+ g_screen_ptr = shadow_fb;
}
void plat_video_flip(void)
{
+ resize_buffers();
+
if (plat_sdl_overlay != NULL) {
SDL_Rect dstrect =
{ 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
-
SDL_LockYUVOverlay(plat_sdl_overlay);
- rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
- g_screen_ppitch * g_screen_height);
+ if (area.w <= plat_sdl_overlay->w && area.h <= plat_sdl_overlay->h)
+ rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
+ area.w, area.h, g_screen_ppitch,
+ plat_sdl_overlay->pitches[0]/2,
+ plat_sdl_overlay->w >= 2*area.w);
SDL_UnlockYUVOverlay(plat_sdl_overlay);
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
}
gl_flip(shadow_fb, g_screen_ppitch, g_screen_height);
}
else {
+ int copy = g_screen_ptr != plat_sdl_screen->pixels;
+ if (copy)
+ copy_intscale(plat_sdl_screen->pixels, plat_sdl_screen->w,
+ plat_sdl_screen->h, plat_sdl_screen->pitch/2,
+ shadow_fb, g_screen_width, g_screen_height, g_screen_ppitch);
+
if (SDL_MUSTLOCK(plat_sdl_screen))
SDL_UnlockSurface(plat_sdl_screen);
SDL_Flip(plat_sdl_screen);
- g_screen_ptr = plat_sdl_screen->pixels;
- PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch * 2);
+
+ // take over resized settings for the physical SDL surface
+ if ((plat_sdl_screen->w != g_menuscreen_w ||
+ plat_sdl_screen->h != g_menuscreen_h) && plat_sdl_is_windowed() &&
+ SDL_WM_GrabInput(SDL_GRAB_ON) == SDL_GRAB_ON) {
+ plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, -1);
+ SDL_WM_GrabInput(SDL_GRAB_OFF);
+ g_menuscreen_pp = plat_sdl_screen->pitch/2;
+
+ // force upper layer to use new dimensions
+ plat_video_set_shadow(g_screen_width, g_screen_height);
+ plat_video_set_buffer(g_screen_ptr);
+ rendstatus_old = -1;
+ } else if (!copy) {
+ g_screen_ppitch = plat_sdl_screen->pitch/2;
+ g_screen_ptr = plat_sdl_screen->pixels;
+ plat_video_set_buffer(g_screen_ptr);
+ }
+
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_LockSurface(plat_sdl_screen);
+
+ if (clear_buf_cnt) {
+ memset(plat_sdl_screen->pixels, 0, plat_sdl_screen->pitch*plat_sdl_screen->h);
+ clear_buf_cnt--;
+ }
+ }
+
+ // for overlay/gl modes buffer ptr may change on resize
+ if ((plat_sdl_overlay || plat_sdl_gl_active) &&
+ (g_screen_ptr != shadow_fb || g_screen_ppitch != g_screen_width)) {
+ g_screen_ppitch = g_screen_width;
+ g_screen_ptr = shadow_fb;
+ plat_video_set_buffer(g_screen_ptr);
+ }
+ if (clear_stat_cnt) {
+ unsigned short *d = (unsigned short *)g_screen_ptr + g_screen_ppitch * g_screen_height;
+ int l = g_screen_ppitch * 8;
+ memset((int *)(d - l), 0, l * 2);
+ clear_stat_cnt--;
}
}
{
}
+void plat_video_clear_status(void)
+{
+ clear_stat_cnt = 3; // do it thrice in case of triple buffering
+}
+
+void plat_video_clear_buffers(void)
+{
+ int count = g_menuscreen_w * g_menuscreen_h;
+ if (count < area.w * area.h) count = area.w * area.h;
+ memset(shadow_fb, 0, count * 2);
+ if (plat_sdl_overlay)
+ plat_sdl_overlay_clear();
+ memset(plat_sdl_screen->pixels, 0, plat_sdl_screen->pitch*plat_sdl_screen->h);
+ clear_buf_cnt = 3; // do it thrice in case of triple buffering
+}
+
+void plat_video_menu_update(void)
+{
+ // WM may grab input while resizing the window; our own window resizing
+ // is only safe if the WM isn't active anymore, so try to grab input.
+ if (plat_sdl_is_windowed() && SDL_WM_GrabInput(SDL_GRAB_ON) == SDL_GRAB_ON) {
+ // w/h might change in resize callback
+ int w, h;
+ do {
+ w = g_menuscreen_w, h = g_menuscreen_h;
+ plat_sdl_change_video_mode(w, h, -1);
+ } while (w != g_menuscreen_w || h != g_menuscreen_h);
+ SDL_WM_GrabInput(SDL_GRAB_OFF);
+ }
+
+ // update pitch as it is needed by the menu bg scaler
+ if (plat_sdl_overlay || plat_sdl_gl_active)
+ g_menuscreen_pp = g_menuscreen_w;
+ else
+ g_menuscreen_pp = plat_sdl_screen->pitch / 2;
+
+ resize_buffers();
+}
+
void plat_video_menu_enter(int is_rom_loaded)
{
- plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 0);
- g_screen_ptr = shadow_fb;
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_UnlockSurface(plat_sdl_screen);
}
void plat_video_menu_begin(void)
{
- if (plat_sdl_overlay != NULL || plat_sdl_gl_active) {
+ plat_video_menu_update(); // just in case
+
+ if (plat_sdl_overlay || plat_sdl_gl_active)
g_menuscreen_ptr = shadow_fb;
- }
else {
if (SDL_MUSTLOCK(plat_sdl_screen))
SDL_LockSurface(plat_sdl_screen);
{ 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
SDL_LockYUVOverlay(plat_sdl_overlay);
- rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
- g_menuscreen_pp * g_menuscreen_h);
+ if (g_menuscreen_w <= plat_sdl_overlay->w && g_menuscreen_h <= plat_sdl_overlay->h)
+ rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
+ g_menuscreen_w, g_menuscreen_h, g_menuscreen_pp,
+ plat_sdl_overlay->pitches[0]/2,
+ plat_sdl_overlay->w >= 2 * g_menuscreen_w);
SDL_UnlockYUVOverlay(plat_sdl_overlay);
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
SDL_Flip(plat_sdl_screen);
}
g_menuscreen_ptr = NULL;
-
}
void plat_video_menu_leave(void)
void plat_video_loop_prepare(void)
{
- plat_sdl_change_video_mode(g_screen_width, g_screen_height, 0);
+ int w = g_menuscreen_w, h = g_menuscreen_h;
- if (plat_sdl_overlay != NULL || plat_sdl_gl_active) {
- g_screen_ptr = shadow_fb;
- }
- else {
+ // take over any new vout settings
+ area = (struct area) { 0, 0 };
+ plat_sdl_change_video_mode(0, 0, 0);
+ resize_buffers();
+
+ // switch over to scaled output if available, but keep the aspect ratio
+ if (plat_sdl_overlay || plat_sdl_gl_active)
+ w = 320, h = 240;
+
+ g_screen_width = w, g_screen_height = h;
+ plat_video_set_size(w, h);
+
+ if (!(plat_sdl_overlay || plat_sdl_gl_active))
if (SDL_MUSTLOCK(plat_sdl_screen))
SDL_LockSurface(plat_sdl_screen);
- g_screen_ptr = plat_sdl_screen->pixels;
- }
- PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch * 2);
+
+ plat_video_set_buffer(g_screen_ptr);
}
-void plat_early_init(void)
+void plat_show_cursor(int on)
+{
+ SDL_ShowCursor(on && !hide_cursor);
+}
+
+int plat_grab_cursor(int on)
{
+ SDL_WM_GrabInput(on ? SDL_GRAB_ON : SDL_GRAB_OFF);
+ return on;
+}
+
+int plat_has_wm(void)
+{
+ return plat_sdl_is_windowed();
+}
+
+static void plat_sdl_resize(int w, int h)
+{
+ // take over new settings
+#if defined(__OPENDINGUX__)
+ if (currentConfig.vscaling != EOPT_SCALE_HW &&
+ plat_sdl_screen->w == 320 && plat_sdl_screen->h == 480) {
+ g_menuscreen_h = 240;
+ g_menuscreen_w = 320;
+ } else
+#endif
+ {
+ g_menuscreen_h = plat_sdl_screen->h;
+ g_menuscreen_w = plat_sdl_screen->w;
+#if 0 // auto resizing may be nice, but creates problems on some SDL platforms
+ if (!plat_sdl_overlay && !plat_sdl_gl_active &&
+ plat_sdl_is_windowed() && !plat_sdl_is_fullscreen()) {
+ // in SDL window mode, adapt window to integer scaling
+ if (g_menuscreen_w * 3/4 >= g_menuscreen_h)
+ g_menuscreen_w = g_menuscreen_h * 4/3;
+ else
+ g_menuscreen_h = g_menuscreen_w * 3/4;
+ g_menuscreen_w = g_menuscreen_w/320*320;
+ g_menuscreen_h = g_menuscreen_h/240*240;
+ if (g_menuscreen_w == 0) {
+ g_menuscreen_w = 320;
+ g_menuscreen_h = 240;
+ }
+ }
+#endif
+ }
+
+ rendstatus_old = -1;
}
static void plat_sdl_quit(void)
void plat_init(void)
{
- int shadow_size;
int ret;
ret = plat_sdl_init();
if (ret != 0)
exit(1);
+#if defined(__OPENDINGUX__)
+ // opendingux on JZ47x0 may falsely report a HW overlay, fix to window
+ plat_target.vout_method = 0;
+#elif !defined(__MIYOO__) && !defined(__RETROFW__) && !defined(__DINGUX__)
+ if (! plat_sdl_is_windowed())
+#endif
+ {
+ hide_cursor = 1;
+ SDL_ShowCursor(0);
+ }
+
plat_sdl_quit_cb = plat_sdl_quit;
+ plat_sdl_resize_cb = plat_sdl_resize;
SDL_WM_SetCaption("PicoDrive " VERSION, NULL);
- g_menuscreen_w = plat_sdl_screen->w;
- g_menuscreen_h = plat_sdl_screen->h;
g_menuscreen_pp = g_menuscreen_w;
g_menuscreen_ptr = NULL;
if (shadow_size < 320 * 480 * 2)
shadow_size = 320 * 480 * 2;
- shadow_fb = malloc(shadow_size);
- g_menubg_ptr = malloc(shadow_size);
+ shadow_fb = calloc(1, shadow_size);
+ g_menubg_ptr = calloc(1, shadow_size);
if (shadow_fb == NULL || g_menubg_ptr == NULL) {
fprintf(stderr, "OOM\n");
exit(1);
g_screen_ppitch = 320;
g_screen_ptr = shadow_fb;
+ plat_target_setup_input();
+ in_sdl_platform_data.defbinds = in_sdl_defbinds,
+ in_sdl_platform_data.kmap_size = in_sdl_key_map_sz,
+ in_sdl_platform_data.key_map = in_sdl_key_map,
+ in_sdl_platform_data.jmap_size = in_sdl_joy_map_sz,
+ in_sdl_platform_data.joy_map = in_sdl_joy_map,
+ in_sdl_platform_data.key_names = in_sdl_key_names,
+ in_sdl_platform_data.kbd_map = in_sdl_kbd_map,
in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler);
in_probe();
+ // create an artificial resize event to initialize mouse scaling
+ SDL_Event ev;
+ ev.resize.type = SDL_VIDEORESIZE;
+ ev.resize.w = g_menuscreen_w;
+ ev.resize.h = g_menuscreen_h;
+ SDL_PeepEvents(&ev, 1, SDL_ADDEVENT, SDL_ALLEVENTS);
+
bgr_to_uyvy_init();
+ linux_menu_init();
}
void plat_finish(void)