From 4c26780f101a12d455ffe900e6a0d5238d1c9552 Mon Sep 17 00:00:00 2001 From: neonloop Date: Sun, 21 Mar 2021 16:41:44 +0000 Subject: Adds a libpicofe frontend and menus Implements: - fast-forward (toggle) - audio-buffer-based frameskip and frame limiting - color-correction (using the libretro code) - lcd ghosting (using the libretro code) - FPS display - input rebinding - emulator key rebinding - scaling (with the old gpsp filters and drowsnug's scaled-nofilter) - saving and savestates - game-specific configuration Not yet implemented: - cheats - fast-forward (hold) --- frontend/plat_linux.c | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 frontend/plat_linux.c (limited to 'frontend/plat_linux.c') diff --git a/frontend/plat_linux.c b/frontend/plat_linux.c new file mode 100644 index 0000000..38e28cc --- /dev/null +++ b/frontend/plat_linux.c @@ -0,0 +1,258 @@ +#include +#include "common.h" + +#include "frontend/main.h" +#include "frontend/plat.h" +#include "frontend/scale.h" +#include "frontend/libpicofe/menu.h" +#include "frontend/libpicofe/plat.h" +#include "frontend/libpicofe/input.h" +#include "frontend/libpicofe/in_sdl.h" + +static SDL_Surface* screen; + +#define BUF_LEN 16384 +static short buf[BUF_LEN]; +static int buf_w, buf_r; + +static char msg[HUD_LEN]; + +static const struct in_default_bind in_sdl_defbinds[] = { + { SDLK_UP, IN_BINDTYPE_PLAYER12, KBIT_UP }, + { SDLK_DOWN, IN_BINDTYPE_PLAYER12, KBIT_DOWN }, + { SDLK_LEFT, IN_BINDTYPE_PLAYER12, KBIT_LEFT }, + { SDLK_RIGHT, IN_BINDTYPE_PLAYER12, KBIT_RIGHT }, + { SDLK_LCTRL, IN_BINDTYPE_PLAYER12, KBIT_B }, + { SDLK_SPACE, IN_BINDTYPE_PLAYER12, KBIT_A }, + { SDLK_RETURN, IN_BINDTYPE_PLAYER12, KBIT_START }, + { SDLK_RCTRL, IN_BINDTYPE_PLAYER12, KBIT_SELECT }, + { SDLK_TAB, IN_BINDTYPE_PLAYER12, KBIT_L }, + { SDLK_BACKSPACE, IN_BINDTYPE_PLAYER12, KBIT_R }, + { SDLK_ESCAPE, IN_BINDTYPE_EMU, EACTION_MENU }, + { 0, 0, 0 } +}; + +const struct menu_keymap in_sdl_key_map[] = +{ + { SDLK_UP, PBTN_UP }, + { SDLK_DOWN, PBTN_DOWN }, + { SDLK_LEFT, PBTN_LEFT }, + { SDLK_RIGHT, PBTN_RIGHT }, + { SDLK_SPACE, PBTN_MOK }, + { SDLK_LCTRL, PBTN_MBACK }, + { SDLK_LALT, PBTN_MA2 }, + { SDLK_LSHIFT, PBTN_MA3 }, + { SDLK_TAB, PBTN_L }, + { SDLK_BACKSPACE, PBTN_R }, +}; + +const struct menu_keymap in_sdl_joy_map[] = +{ + { SDLK_UP, PBTN_UP }, + { SDLK_DOWN, PBTN_DOWN }, + { SDLK_LEFT, PBTN_LEFT }, + { SDLK_RIGHT, PBTN_RIGHT }, + { SDLK_WORLD_0, PBTN_MOK }, + { SDLK_WORLD_1, PBTN_MBACK }, + { SDLK_WORLD_2, PBTN_MA2 }, + { SDLK_WORLD_3, PBTN_MA3 }, +}; + +static const struct in_pdata in_sdl_platform_data = { + .defbinds = in_sdl_defbinds, + .key_map = in_sdl_key_map, + .kmap_size = array_size(in_sdl_key_map), + .joy_map = in_sdl_joy_map, + .jmap_size = array_size(in_sdl_joy_map), +}; + +static void *fb_flip(void) +{ + SDL_Flip(screen); + return screen->pixels; +} + +void plat_video_menu_enter(int is_rom_loaded) +{ +} + +void plat_video_menu_begin(void) +{ + g_menuscreen_ptr = fb_flip(); +} + +void plat_video_menu_end(void) +{ + g_menuscreen_ptr = fb_flip(); +} + +void plat_video_menu_leave(void) +{ + SDL_LockSurface(screen); + memset(g_menuscreen_ptr, 0, 320 * 240 * sizeof(uint16_t)); + SDL_UnlockSurface(screen); + g_menuscreen_ptr = fb_flip(); + SDL_LockSurface(screen); + memset(g_menuscreen_ptr, 0, 320 * 240 * sizeof(uint16_t)); + SDL_UnlockSurface(screen); +} + +void plat_video_open(void) +{ +} + +void plat_video_set_msg(char *new_msg) +{ + snprintf(msg, HUD_LEN, "%s", new_msg); +} + +void plat_video_flip(void) +{ + video_post_process(); + SDL_LockSurface(screen); + if (msg[0]) + video_clear_msg(screen->pixels, screen->h, screen->pitch / sizeof(uint16_t)); + + video_scale(screen->pixels, screen->h, screen->pitch / sizeof(uint16_t)); + + if (msg[0]) + video_print_msg(screen->pixels, screen->h, screen->pitch / sizeof(uint16_t), msg); + SDL_UnlockSurface(screen); + + g_menuscreen_ptr = fb_flip(); + msg[0] = 0; +} + +void plat_video_close(void) +{ +} + +void plat_sound_callback(void *unused, u8 *stream, int len) +{ + short *p = (short *)stream; + len /= sizeof(short); + + while (buf_r != buf_w && len > 0) { + *p++ = buf[buf_r++]; + buf_r %= BUF_LEN; + --len; + } + + while(len > 0) { + *p++ = 0; + --len; + } +} + +void plat_sound_finish(void) +{ + SDL_PauseAudio(1); + SDL_CloseAudio(); +} + +int plat_sound_init(void) +{ + + if (SDL_InitSubSystem(SDL_INIT_AUDIO)) { + return -1; + } + + SDL_AudioSpec spec; + + spec.freq = sound_frequency; + spec.format = AUDIO_S16; + spec.channels = 2; + spec.samples = 512; + spec.callback = plat_sound_callback; + + if (SDL_OpenAudio(&spec, NULL) < 0) { + plat_sound_finish(); + return -1; + } + + SDL_PauseAudio(0); + return 0; +} + +float plat_sound_capacity(void) +{ + int buffered = 0; + if (buf_w != buf_r) { + buffered = buf_w > buf_r ? buf_w - buf_r : (buf_w + BUF_LEN) - buf_r; + } + + return 1.0 - (float)buffered / BUF_LEN; +} + +void plat_sound_write(void *data, int bytes) +{ + short *sound_data = (short *)data; + SDL_LockAudio(); + + while (bytes > 0) { + while (((buf_w + 1) % BUF_LEN) == buf_r) { + SDL_UnlockAudio(); + + if (!limit_frames) + return; + + plat_sleep_ms(1); + SDL_LockAudio(); + } + + buf[buf_w] = *sound_data++; + + ++buf_w; + buf_w %= BUF_LEN; + bytes -= sizeof(short); + } + SDL_UnlockAudio(); +} + +void plat_sdl_event_handler(void *event_) +{ +} + +int plat_init(void) +{ + SDL_Init(SDL_INIT_VIDEO); + screen = SDL_SetVideoMode(320, 240, 16, SDL_SWSURFACE); + + if (screen == NULL) { + printf("%s, failed to set video mode\n", __func__); + return -1; + } + + SDL_ShowCursor(0); + + g_menuscreen_w = 320; + g_menuscreen_h = 240; + g_menuscreen_pp = 320; + g_menuscreen_ptr = fb_flip(); + + if (in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler)) { + fprintf(stderr, "SDL input failed to init: %s\n", SDL_GetError()); + return -1; + } + in_probe(); + + if (plat_sound_init()) { + fprintf(stderr, "SDL sound failed to init: %s\n", SDL_GetError()); + return -1; + } + return 0; +} + +void plat_pre_finish(void) +{ +} + +void plat_finish(void) +{ + plat_sound_finish(); + SDL_Quit(); +} + +void plat_trigger_vibrate(int pad, int low, int high) +{ +} -- cgit v1.2.3