diff options
Diffstat (limited to 'frontend/plat_trimui.c')
-rw-r--r-- | frontend/plat_trimui.c | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/frontend/plat_trimui.c b/frontend/plat_trimui.c new file mode 100644 index 0000000..6b1038a --- /dev/null +++ b/frontend/plat_trimui.c @@ -0,0 +1,382 @@ +/* + * 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 + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <SDL.h> + +#include "main.h" +#include "menu.h" +#include "plat.h" +#include "cspace.h" +#include "blit320.h" +#include "plugin_lib.h" +#include "libpicofe/menu.h" +#include "libpicofe/plat.h" +#include "libpicofe/input.h" +#include "libpicofe/in_sdl.h" +#include "../libpcsxcore/psxmem_map.h" + +SDL_Surface* screen; +struct plat_target plat_target; + +static unsigned short *psx_vram; +static unsigned short *cspace_buf; +static int psx_step, psx_width, psx_height, psx_bpp; +static int psx_offset_x, psx_offset_y, psx_src_width, psx_src_height; +static int fb_offset_x, fb_offset_y; + +static const struct in_default_bind in_sdl_defbinds[] = { + { SDLK_UP, IN_BINDTYPE_PLAYER12, DKEY_UP }, + { SDLK_DOWN, IN_BINDTYPE_PLAYER12, DKEY_DOWN }, + { SDLK_LEFT, IN_BINDTYPE_PLAYER12, DKEY_LEFT }, + { SDLK_RIGHT, IN_BINDTYPE_PLAYER12, DKEY_RIGHT }, + { SDLK_LSHIFT, IN_BINDTYPE_PLAYER12, DKEY_TRIANGLE }, + { SDLK_LCTRL, IN_BINDTYPE_PLAYER12, DKEY_CROSS }, + { SDLK_SPACE, IN_BINDTYPE_PLAYER12, DKEY_CIRCLE }, + { SDLK_LALT, IN_BINDTYPE_PLAYER12, DKEY_SQUARE }, + { SDLK_RETURN, IN_BINDTYPE_PLAYER12, DKEY_START }, + { SDLK_RCTRL, IN_BINDTYPE_PLAYER12, DKEY_SELECT }, + { SDLK_TAB, IN_BINDTYPE_PLAYER12, DKEY_L1 }, + { SDLK_BACKSPACE, IN_BINDTYPE_PLAYER12, DKEY_R1 }, + { SDLK_e, IN_BINDTYPE_PLAYER12, DKEY_L2 }, + { SDLK_t, IN_BINDTYPE_PLAYER12, DKEY_R2 }, + { SDLK_ESCAPE, IN_BINDTYPE_EMU, SACTION_ENTER_MENU }, + { SDLK_F1, IN_BINDTYPE_EMU, SACTION_SAVE_STATE }, + { SDLK_F2, IN_BINDTYPE_EMU, SACTION_LOAD_STATE }, + { SDLK_F3, IN_BINDTYPE_EMU, SACTION_PREV_SSLOT }, + { SDLK_F4, IN_BINDTYPE_EMU, SACTION_NEXT_SSLOT }, + { SDLK_F5, IN_BINDTYPE_EMU, SACTION_TOGGLE_FSKIP }, + { SDLK_F6, IN_BINDTYPE_EMU, SACTION_SCREENSHOT }, + { SDLK_F7, IN_BINDTYPE_EMU, SACTION_TOGGLE_FPS }, + { SDLK_F8, IN_BINDTYPE_EMU, SACTION_SWITCH_DISPMODE }, + { SDLK_F11, IN_BINDTYPE_EMU, SACTION_TOGGLE_FULLSCREEN }, + { SDLK_F12, IN_BINDTYPE_EMU, SACTION_FAST_FORWARD }, + { 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 char * const in_sdl_key_names[SDLK_LAST] = { + [SDLK_UP] = "up", + [SDLK_DOWN] = "down", + [SDLK_LEFT] = "left", + [SDLK_RIGHT] = "right", + [SDLK_LSHIFT] = "x", + [SDLK_LCTRL] = "b", + [SDLK_SPACE] = "a", + [SDLK_LALT] = "y", + [SDLK_RETURN] = "start", + [SDLK_RCTRL] = "select", + [SDLK_TAB] = "l", + [SDLK_BACKSPACE] = "r", + [SDLK_ESCAPE] = "menu", +}; + +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, +}; + +static void *fb_flip(void) +{ + static int flip=0; + + { + flip^=1; + 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) +{ + if (psx_vram == NULL) { + printf("%s, GPU plugin did not provide vram\n", __func__); + exit(-1); + } + + 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_prepare_screenshot(int *w, int *h, int *bpp) +{ + *w = 320; + *h = 240; + *bpp = psx_bpp; + return pl_vout_buf; +} + +void plat_minimize(void) +{ +} + +#define make_flip_func(name, scale, blitfunc) \ + static void name(int doffs, const void *vram_, int w, int h, int sstride, int bgr24) \ + { \ + const unsigned short *vram = vram_; \ + unsigned char *conv = (unsigned char *)cspace_buf; \ + unsigned char *dst = (unsigned char *)screen->pixels + \ + (fb_offset_y * 320 + fb_offset_x) * sizeof(uint16_t); \ + int dst_stride = 640; \ + int len = psx_src_width * psx_bpp / 8; \ + int i; \ + void (*convertfunc)(void *dst, const void *src, int bytes); \ + convertfunc = psx_bpp == 24 ? bgr888_to_rgb565 : bgr555_to_rgb565; \ + \ + SDL_LockSurface(screen); \ + vram += psx_offset_y * 1024 + psx_offset_x; \ + for (i = psx_src_height; i > 0; i--, \ + vram += psx_step * 1024, \ + dst += dst_stride, \ + conv += dst_stride) { \ + if (scale) { \ + convertfunc(conv, vram, len); \ + blitfunc(dst, conv, dst_stride); \ + } else { \ + convertfunc(dst, vram, len); \ + } \ + } \ + SDL_UnlockSurface(screen); \ + } + +make_flip_func(raw_blit_soft, false, memcpy) +make_flip_func(raw_blit_soft_368, true, blit320_368) +make_flip_func(raw_blit_soft_512, true, blit320_512) +make_flip_func(raw_blit_soft_640, true, blit320_640) + +void *plat_gvideo_set_mode(int *w_, int *h_, int *bpp_) +{ + int poff_w, poff_h, w_max; + int w = *w_, h = *h_, bpp = *bpp_; + + if (!w || !h || !bpp) + return NULL; + + printf("psx mode: %dx%d@%d\n", w, h, bpp); + psx_width = w; + psx_height = h; + psx_bpp = bpp; + + switch (w + (bpp != 16) + !soft_scaling) { + case 640: + pl_plat_blit = raw_blit_soft_640; + w_max = 640; + break; + case 512: + pl_plat_blit = raw_blit_soft_512; + w_max = 512; + break; + case 384: + case 368: + pl_plat_blit = raw_blit_soft_368; + w_max = 368; + break; + default: + pl_plat_blit = raw_blit_soft; + w_max = 320; + break; + } + + psx_step = 1; + if (h > 256) { + psx_step = 2; + h /= 2; + } + + poff_w = poff_h = 0; + if (w > w_max) { + poff_w = w / 2 - w_max / 2; + w = w_max; + } + fb_offset_x = 0; + if (w < 320) + fb_offset_x = 320/2 - w / 2; + if (h > 240) { + poff_h = h / 2 - 240/2; + h = 240; + } + fb_offset_y = 240/2 - h / 2; + + psx_offset_x = poff_w * psx_bpp/8 / 2; + psx_offset_y = poff_h; + psx_src_width = w; + psx_src_height = h; + + if (fb_offset_x || fb_offset_y) { + // not fullscreen, must clear borders + 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); + memset(cspace_buf, 0, 320*240 * sizeof(uint16_t)); + } + + // adjust for hud + *w_ = 320; + *h_ = fb_offset_y + psx_src_height; + return g_menuscreen_ptr; +} + +/* not really used, we do raw_flip */ +void plat_gvideo_open(int is_pal) +{ +} + +void *plat_gvideo_flip(void) +{ + g_menuscreen_ptr = fb_flip(); + return g_menuscreen_ptr; +} + +void plat_gvideo_close(void) +{ +} + +static void *pl_emu_mmap(unsigned long addr, size_t size, int is_fixed, enum psxMapTag tag) +{ + void *retval; + + retval = plat_mmap(addr, size, 0, is_fixed); + if (tag == MAP_TAG_VRAM) { + psx_vram = retval; + } + return retval; +} + +static void pl_emu_munmap(void *ptr, size_t size, enum psxMapTag tag) +{ + plat_munmap(ptr, size); +} + +void plat_sdl_event_handler(void *event_) +{ +} + +void plat_init(void) +{ + if (SDL_WasInit(SDL_INIT_EVERYTHING)) { + SDL_InitSubSystem(SDL_INIT_VIDEO); + } + else { + 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__); + exit(-1); + } + SDL_ShowCursor(0); + system("echo 10 > /proc/sys/vm/swappiness"); + + cspace_buf = calloc(1, 640 * 480 * sizeof(uint16_t)); + if (!cspace_buf) { + printf("%s, failed to allocate color conversion buffer\n", __func__); + exit(-1); + } + + g_menuscreen_w = 320; + g_menuscreen_h = 240; + g_menuscreen_pp = 320; + g_menuscreen_ptr = fb_flip(); + + in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler); + in_probe(); + + pl_plat_blit = raw_blit_soft; + psx_src_width = 320; + psx_src_height = 240; + psx_bpp = 16; + + pl_rearmed_cbs.screen_w = 320; + pl_rearmed_cbs.screen_h = 240; + psxMapHook = pl_emu_mmap; + psxUnmapHook = pl_emu_munmap; + in_enable_vibration = 1; +} + +void plat_pre_finish(void) +{ + system("echo 60 > /proc/sys/vm/swappiness"); +} + +void plat_finish(void) +{ + if (cspace_buf) { + free(cspace_buf); + } + + SDL_Quit(); +} + +void plat_trigger_vibrate(int pad, int low, int high) +{ +} |