#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#ifndef _WIN32
#include <sys/mman.h>
+#else
+#include <windows.h>
+#endif
+#include <errno.h>
#ifdef __MACH__
#include <libkern/OSCacheControl.h>
#endif
#include <pico/pico_int.h>
+#include <pico/state.h>
#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;
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
#endif
}
-void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed)
+#ifdef _WIN32
+void* mmap(void *desired_addr,
+ size_t len,
+ int mmap_prot,
+ int mmap_flags,
+ HANDLE fd,
+ size_t off)
{
- int flags = MAP_PRIVATE | MAP_ANONYMOUS;
- void *req, *ret;
-
- req = (void *)addr;
- ret = mmap(req, size, PROT_READ | PROT_WRITE, flags, -1, 0);
- if (ret == MAP_FAILED)
- return NULL;
-
- if (addr != 0 && ret != (void *)addr) {
- lprintf("warning: wanted to map @%08lx, got %p\n",
- addr, ret);
+ return malloc(len);
+}
- if (is_fixed) {
- munmap(ret, size);
- return NULL;
- }
- }
+void munmap(
+ void *base_addr,
+ size_t len
+)
+{
+ free(base_addr);
+}
+#define MAP_FAILED 0
+#define PROT_READ 0
+#define PROT_WRITE 0
+#define MAP_PRIVATE 0
+#define MAP_ANONYMOUS 0
+#endif
+void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed)
+{
+#ifndef _WIN32
+ int flags = 0;
+ void *ret = mmap((void*)addr,size,PROT_READ | PROT_WRITE, flags, -1, 0);
+ if (addr != 0 && ret != (void *)addr) {
+ lprintf("warning: wanted to map @%08lx, got %p\n",
+ addr, ret);
+
+ if (is_fixed) {
+ munmap(ret, size);
+ return NULL;
+ }
+ }
+#else
+ int flags = MAP_PRIVATE | MAP_ANONYMOUS;
+ void *req, *ret;
+
+ req = (void *)addr;
+ ret = mmap(req, size, PROT_READ | PROT_WRITE, flags, -1, 0);
+ 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",
+ addr, ret);
+
+ if (is_fixed) {
+ munmap(ret, size);
+ return NULL;
+ }
+ }
+#endif
return ret;
}
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)
munmap(ptr, size);
}
+int plat_mem_set_exec(void *ptr, size_t size)
+{
+#ifdef _WIN32
+ int ret = VirtualProtect(ptr,size,PAGE_EXECUTE_READWRITE,0);
+ if (ret == 0)
+ lprintf("mprotect(%p, %zd) failed: %d\n", ptr, size, 0);
+#else
+ int ret = mprotect(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC);
+ if (ret != 0)
+ lprintf("mprotect(%p, %zd) failed: %d\n", ptr, size, errno);
+#endif
+ return ret;
+}
+
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
{
memset(vout_buf, 0, 320 * 240 * 2);
void emu_32x_startup(void)
{
- PicoDrawSetOutFormat(PDF_RGB555, 1);
}
#ifndef ANDROID
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;
}
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 */
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;