Add mman wrapper for Win32 and use it for PCSX ReARmed libretro Win32
authortwinaphex <libretro@gmail.com>
Sat, 13 Dec 2014 04:53:54 +0000 (05:53 +0100)
committertwinaphex <libretro@gmail.com>
Sat, 13 Dec 2014 04:53:54 +0000 (05:53 +0100)
Makefile
Makefile.libretro
libpcsxcore/memmap.h [new file with mode: 0644]
libpcsxcore/memmap_win32.c [new file with mode: 0644]
libpcsxcore/psxmem.c

index 6187958..9568d0e 100644 (file)
--- 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"
index b92cea4..6d37652 100644 (file)
@@ -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 (file)
index 0000000..e80d720
--- /dev/null
@@ -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 <sys/types.h>
+
+#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 <sys/mman.h>
+#endif
+
+#endif
+
+#endif
diff --git a/libpcsxcore/memmap_win32.c b/libpcsxcore/memmap_win32.c
new file mode 100644 (file)
index 0000000..f4dbdd6
--- /dev/null
@@ -0,0 +1,173 @@
+#include <windows.h>
+#include <errno.h>
+#include <io.h>
+
+#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;
+}
+
index 7001744..259128d 100644 (file)
 #include "r3000a.h"
 #include "psxhw.h"
 #include "debug.h"
+
+#ifdef __LIBRETRO__
+#include "memmap.h"
+#else
 #include <sys/mman.h>
+#endif
 
 #ifndef MAP_ANONYMOUS
 #define MAP_ANONYMOUS MAP_ANON