From 3a92bf0b7a2d929f53ae69cf761721c136f9036d Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 13 Dec 2014 05:53:54 +0100 Subject: Add mman wrapper for Win32 and use it for PCSX ReARmed libretro Win32 --- Makefile | 4 ++ Makefile.libretro | 4 ++ libpcsxcore/memmap.h | 60 ++++++++++++++++ libpcsxcore/memmap_win32.c | 173 +++++++++++++++++++++++++++++++++++++++++++++ libpcsxcore/psxmem.c | 5 ++ 5 files changed, 246 insertions(+) create mode 100644 libpcsxcore/memmap.h create mode 100644 libpcsxcore/memmap_win32.c diff --git a/Makefile b/Makefile index 6187958..9568d0e 100644 --- a/Makefile +++ b/Makefile @@ -195,6 +195,10 @@ endif ifeq "$(PLATFORM)" "libretro" OBJS += frontend/libretro.o CFLAGS += -DFRONTEND_SUPPORTS_RGB565 + +ifeq ($(MMAP_WIN32),1) +OBJS += libpcsxcore/memmap_win32.o +endif endif ifeq "$(USE_PLUGIN_LIB)" "1" diff --git a/Makefile.libretro b/Makefile.libretro index b92cea4..6d37652 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -1,5 +1,8 @@ # Makefile for PCSX ReARMed (libretro) +DEBUG=1 +MMAP_WIN32=0 + ifeq ($(platform),) platform = unix ifeq ($(shell uname -a),) @@ -147,6 +150,7 @@ else CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ BUILTIN_GPU = neon CFLAGS += -DNEON_PC + MMAP_WIN32=1 endif CFLAGS += -fPIC diff --git a/libpcsxcore/memmap.h b/libpcsxcore/memmap.h new file mode 100644 index 0000000..e80d720 --- /dev/null +++ b/libpcsxcore/memmap.h @@ -0,0 +1,60 @@ +#ifndef _MEMMAP_H +#define _MEMMAP_H + +#ifdef HAVE_MMAP + +#ifdef _WIN32 + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +/* All the headers include this file. */ +#ifndef _MSC_VER +#include <_mingw.h> +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 + +#define MAP_FILE 0 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_TYPE 0xf +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_ANON MAP_ANONYMOUS + +#define MAP_FAILED ((void *)-1) + +/* Flags for msync. */ +#define MS_ASYNC 1 +#define MS_SYNC 2 +#define MS_INVALIDATE 4 + +void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); +int munmap(void *addr, size_t len); +int mprotect(void *addr, size_t len, int prot); +int msync(void *addr, size_t len, int flags); +int mlock(const void *addr, size_t len); +int munlock(const void *addr, size_t len); + +#ifdef __cplusplus +}; +#endif + +#else +#include +#endif + +#endif + +#endif diff --git a/libpcsxcore/memmap_win32.c b/libpcsxcore/memmap_win32.c new file mode 100644 index 0000000..f4dbdd6 --- /dev/null +++ b/libpcsxcore/memmap_win32.c @@ -0,0 +1,173 @@ +#include +#include +#include + +#include "mman.h" + +#ifndef FILE_MAP_EXECUTE +#define FILE_MAP_EXECUTE 0x0020 +#endif /* FILE_MAP_EXECUTE */ + +static int __map_mman_error(const DWORD err, const int deferr) +{ + if (err == 0) + return 0; + /* TODO: implement */ + return err; +} + +static DWORD __map_mmap_prot_page(const int prot) +{ + DWORD protect = 0; + + if (prot == PROT_NONE) + return 0; + + if ((prot & PROT_EXEC) != 0) + protect = ((prot & PROT_WRITE) != 0) ? + PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; + else + protect = ((prot & PROT_WRITE) != 0) ? + PAGE_READWRITE : PAGE_READONLY; + + return protect; +} + +static DWORD __map_mmap_prot_file(const int prot) +{ + DWORD desiredAccess = 0; + + if (prot == PROT_NONE) + return 0; + + if ((prot & PROT_READ) != 0) + desiredAccess |= FILE_MAP_READ; + if ((prot & PROT_WRITE) != 0) + desiredAccess |= FILE_MAP_WRITE; + if ((prot & PROT_EXEC) != 0) + desiredAccess |= FILE_MAP_EXECUTE; + + return desiredAccess; +} + +void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) +{ + HANDLE fm, h; + + void * map = MAP_FAILED; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4293) +#endif + + const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ? + (DWORD)off : (DWORD)(off & 0xFFFFFFFFL); + const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ? + (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL); + const DWORD protect = __map_mmap_prot_page(prot); + const DWORD desiredAccess = __map_mmap_prot_file(prot); + + const off_t maxSize = off + (off_t)len; + + const DWORD dwMaxSizeLow = (sizeof(off_t) <= sizeof(DWORD)) ? + (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL); + const DWORD dwMaxSizeHigh = (sizeof(off_t) <= sizeof(DWORD)) ? + (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL); + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + errno = 0; + + if (len == 0 + /* Unsupported flag combinations */ + || (flags & MAP_FIXED) != 0 + /* Usupported protection combinations */ + || prot == PROT_EXEC) + { + errno = EINVAL; + return MAP_FAILED; + } + + h = ((flags & MAP_ANONYMOUS) == 0) ? + (HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE; + + if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return MAP_FAILED; + } + + fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL); + + if (!fm) + goto error; + + map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len); + + CloseHandle(fm); + + if (!map) + goto error; + + return map; +error: + errno = __map_mman_error(GetLastError(), EPERM); + return MAP_FAILED; +} + +int munmap(void *addr, size_t len) +{ + if (UnmapViewOfFile(addr)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + +int mprotect(void *addr, size_t len, int prot) +{ + DWORD newProtect = __map_mmap_prot_page(prot); + DWORD oldProtect = 0; + + if (VirtualProtect(addr, len, newProtect, &oldProtect)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + +int msync(void *addr, size_t len, int flags) +{ + if (FlushViewOfFile(addr, len)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + +int mlock(const void *addr, size_t len) +{ + if (VirtualLock((LPVOID)addr, len)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + +int munlock(const void *addr, size_t len) +{ + if (VirtualUnlock((LPVOID)addr, len)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 7001744..259128d 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -28,7 +28,12 @@ #include "r3000a.h" #include "psxhw.h" #include "debug.h" + +#ifdef __LIBRETRO__ +#include "memmap.h" +#else #include +#endif #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON -- cgit v1.2.3