X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=platform%2Flibretro.c;h=3ae8974027446291a2b67d6142621f7e2dbf6358;hb=08769494e89920b5987f10c9d15e33e4e0110930;hp=40dc394e96b42e7adca43b1bcda9b253b09ccf28;hpb=2446536be520914616403876d7e49621ac6f4b95;p=picodrive.git diff --git a/platform/libretro.c b/platform/libretro.c index 40dc394..3ae8974 100644 --- a/platform/libretro.c +++ b/platform/libretro.c @@ -11,15 +11,21 @@ #include #include #include +#include #ifdef __MACH__ #include #endif #include +#include #include "common/input_pico.h" #include "common/version.h" #include "libretro.h" +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + static retro_video_refresh_t video_cb; static retro_input_poll_t input_poll_cb; static retro_input_state_t input_state_cb; @@ -35,10 +41,6 @@ static int vout_width, vout_height; static short __attribute__((aligned(4))) sndBuffer[2*44100/50]; -// FIXME: these 2 shouldn't be here -static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)]; -unsigned char *PicoDraw2FB = PicoDraw2FB_; - static void snd_write(int len); #ifdef _WIN32 @@ -71,8 +73,10 @@ void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed) req = (void *)addr; ret = mmap(req, size, PROT_READ | PROT_WRITE, flags, -1, 0); - if (ret == MAP_FAILED) + if (ret == MAP_FAILED) { + lprintf("mmap(%08lx, %zd) failed: %d\n", addr, size, errno); return NULL; + } if (addr != 0 && ret != (void *)addr) { lprintf("warning: wanted to map @%08lx, got %p\n", @@ -89,11 +93,35 @@ void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed) void *plat_mremap(void *ptr, size_t oldsize, size_t newsize) { +#ifdef __linux__ void *ret = mremap(ptr, oldsize, newsize, 0); if (ret == MAP_FAILED) return NULL; return ret; +#else + void *tmp, *ret; + size_t preserve_size; + + preserve_size = oldsize; + if (preserve_size > newsize) + preserve_size = newsize; + tmp = malloc(preserve_size); + if (tmp == NULL) + return NULL; + memcpy(tmp, ptr, preserve_size); + + munmap(ptr, oldsize); + ret = mmap(ptr, newsize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ret == MAP_FAILED) { + free(tmp); + return NULL; + } + memcpy(ret, tmp, preserve_size); + free(tmp); + return ret; +#endif } void plat_munmap(void *ptr, size_t size) @@ -102,6 +130,15 @@ void plat_munmap(void *ptr, size_t size) munmap(ptr, size); } +int plat_mem_set_exec(void *ptr, size_t size) +{ + int ret = mprotect(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC); + if (ret != 0) + lprintf("mprotect(%p, %zd) failed: %d\n", ptr, size, errno); + + return ret; +} + void emu_video_mode_change(int start_line, int line_count, int is_32cols) { memset(vout_buf, 0, 320 * 240 * 2); @@ -111,7 +148,6 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols) void emu_32x_startup(void) { - PicoDrawSetOutFormat(PDF_RGB555, 1); } #ifndef ANDROID @@ -147,6 +183,8 @@ void retro_set_environment(retro_environment_t cb) { static const struct retro_variable vars[] = { //{ "region", "Region; Auto|NTSC|PAL" }, + { "picodrive_input1", "Input device 1; 3 button pad|6 button pad|None" }, + { "picodrive_input2", "Input device 2; 3 button pad|6 button pad|None" }, { NULL, NULL }, }; @@ -175,7 +213,7 @@ void retro_get_system_info(struct retro_system_info *info) memset(info, 0, sizeof(*info)); info->library_name = "PicoDrive"; info->library_version = VERSION; - info->valid_extensions = "bin|gen|smd|32x|cue|iso|sms"; + info->valid_extensions = "bin|gen|smd|md|32x|cue|iso|sms"; info->need_fullpath = true; } @@ -191,20 +229,124 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->geometry.aspect_ratio = 4.0 / 3.0; } -/* savestates - TODO */ +/* savestates */ +struct savestate_state { + const char *load_buf; + char *save_buf; + size_t size; + size_t pos; +}; + +size_t state_read(void *p, size_t size, size_t nmemb, void *file) +{ + struct savestate_state *state = file; + size_t bsize = size * nmemb; + + if (state->pos + bsize > state->size) { + lprintf("savestate error: %u/%u\n", + state->pos + bsize, state->size); + bsize = state->size - state->pos; + if ((int)bsize <= 0) + return 0; + } + + memcpy(p, state->load_buf + state->pos, bsize); + state->pos += bsize; + return bsize; +} + +size_t state_write(void *p, size_t size, size_t nmemb, void *file) +{ + struct savestate_state *state = file; + size_t bsize = size * nmemb; + + if (state->pos + bsize > state->size) { + lprintf("savestate error: %u/%u\n", + state->pos + bsize, state->size); + bsize = state->size - state->pos; + if ((int)bsize <= 0) + return 0; + } + + memcpy(state->save_buf + state->pos, p, bsize); + state->pos += bsize; + return bsize; +} + +size_t state_skip(void *p, size_t size, size_t nmemb, void *file) +{ + struct savestate_state *state = file; + size_t bsize = size * nmemb; + + state->pos += bsize; + return bsize; +} + +size_t state_eof(void *file) +{ + struct savestate_state *state = file; + + return state->pos >= state->size; +} + +int state_fseek(void *file, long offset, int whence) +{ + struct savestate_state *state = file; + + switch (whence) { + case SEEK_SET: + state->pos = offset; + break; + case SEEK_CUR: + state->pos += offset; + break; + case SEEK_END: + state->pos = state->size + offset; + break; + } + return (int)state->pos; +} + +/* savestate sizes vary wildly depending if cd/32x or + * carthw is active, so run the whole thing to get size */ size_t retro_serialize_size(void) { - return 0; + struct savestate_state state = { 0, }; + int ret; + + ret = PicoStateFP(&state, 1, NULL, state_skip, NULL, state_fseek); + if (ret != 0) + return 0; + + return state.pos; } bool retro_serialize(void *data, size_t size) { - return false; + struct savestate_state state = { 0, }; + int ret; + + state.save_buf = data; + state.size = size; + state.pos = 0; + + ret = PicoStateFP(&state, 1, NULL, state_write, + NULL, state_fseek); + return ret == 0; } bool retro_unserialize(const void *data, size_t size) { - return false; + struct savestate_state state = { 0, }; + int ret; + + state.load_buf = data; + state.size = size; + state.pos = 0; + + ret = PicoStateFP(&state, 0, state_read, NULL, + state_eof, state_fseek); + return ret == 0; } /* cheats - TODO */ @@ -405,7 +547,7 @@ bool retro_load_game(const struct retro_game_info *info) enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565; if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { - lprintf("RGB565 suppot required, sorry\n"); + lprintf("RGB565 support required, sorry\n"); return false; } @@ -520,13 +662,41 @@ static void snd_write(int len) audio_batch_cb(PsndOut, len / 4); } +static enum input_device input_name_to_val(const char *name) +{ + if (strcmp(name, "3 button pad") == 0) + return PICO_INPUT_PAD_3BTN; + if (strcmp(name, "6 button pad") == 0) + return PICO_INPUT_PAD_6BTN; + if (strcmp(name, "None") == 0) + return PICO_INPUT_NOTHING; + + lprintf("invalid picodrive_input: '%s'\n", name); + return PICO_INPUT_PAD_3BTN; +} + +static void update_variables(void) +{ + struct retro_variable var; + + var.value = NULL; + var.key = "picodrive_input1"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + PicoSetInputDevice(0, input_name_to_val(var.value)); + + var.value = NULL; + var.key = "picodrive_input2"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + PicoSetInputDevice(1, input_name_to_val(var.value)); +} + void retro_run(void) { bool updated = false; int pad, i; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) - ; //update_variables(true); + update_variables(); input_poll_cb(); @@ -559,27 +729,29 @@ void retro_init(void) environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_control); PicoOpt = POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 - | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_SVP_DRC - | POPT_ACC_SPRITES|POPT_EN_32X|POPT_EN_PWM - | POPT_DIS_32C_BORDER; + | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX + | POPT_EN_32X|POPT_EN_PWM + | POPT_ACC_SPRITES|POPT_DIS_32C_BORDER; +#ifdef __arm__ + PicoOpt |= POPT_EN_SVP_DRC; +#endif PsndRate = 44100; PicoAutoRgnOrder = 0x184; // US, EU, JP PicoCDBuffers = 0; - p32x_msh2_multiplier = MSH2_MULTI_DEFAULT; - p32x_ssh2_multiplier = SSH2_MULTI_DEFAULT; - vout_width = 320; vout_height = 240; vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); PicoInit(); - PicoDrawSetOutFormat(PDF_RGB555, 1); + PicoDrawSetOutFormat(PDF_RGB555, 0); PicoDrawSetOutBuf(vout_buf, vout_width * 2); //PicoMessage = plat_status_msg_busy_next; PicoMCDopenTray = disk_tray_open; PicoMCDcloseTray = disk_tray_close; + + update_variables(); } void retro_deinit(void)