From 5820d8be949f175ccafe2770295d99c3132056c5 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 13 Dec 2014 05:50:15 +0100 Subject: Create memmap_win32.c for Win32 systems - a mman wrapper --- Makefile | 42 ++++++++++---- Makefile.common | 7 ++- libretro.c | 5 +- memmap.h | 60 ++++++++++++++++++++ memmap_win32.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 270 insertions(+), 17 deletions(-) create mode 100644 memmap.h create mode 100644 memmap_win32.c diff --git a/Makefile b/Makefile index 65c6470..1d887cc 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,8 @@ DEBUG=0 HAVE_GRIFFIN=0 FRONTEND_SUPPORTS_RGB565=1 FORCE_32BIT_ARCH=0 +HAVE_MMAP=0 +HAVE_MMAP_WIN32=0 ifneq ($(EMSCRIPTEN),) platform = emscripten @@ -69,14 +71,18 @@ ifeq ($(platform), unix) ifneq ($(findstring Haiku,$(shell uname -a)),) LIBM := endif - CFLAGS += $(FORCE_32BIT) -DHAVE_MMAP + CFLAGS += $(FORCE_32BIT) LDFLAGS := -Wl,--no-undefined + +ifeq ($(HAVE_DYNAREC),1) + HAVE_MMAP = 1 +endif # OS X else ifeq ($(platform), osx) TARGET := $(TARGET_NAME)_libretro.dylib fpic := -fPIC ifeq ($(arch),ppc) - CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + CFLAGS += -DMSB_FIRST -D__ppc__ endif OSXVER = `sw_vers -productVersion | cut -d. -f 2` OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` @@ -84,7 +90,10 @@ else ifeq ($(platform), osx) fpic += -mmacosx-version-min=10.5 endif SHARED := -dynamiclib - CFLAGS += -DHAVE_MMAP + +ifeq ($(HAVE_DYNAREC),1) + HAVE_MMAP = 1 +endif # iOS else ifeq ($(platform), ios) @@ -98,7 +107,7 @@ else ifeq ($(platform), ios) endif CC = clang -arch armv7 -isysroot $(IOSSDK) - CFLAGS += -DIOS -DHAVE_MMAP -DHAVE_POSIX_MEMALIGN -marm + CFLAGS += -DIOS -DHAVE_POSIX_MEMALIGN -marm OSXVER = `sw_vers -productVersion | cut -d. -f 2` OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` ifeq ($(OSX_LT_MAVERICKS),"YES") @@ -111,7 +120,7 @@ else ifeq ($(platform), qnx) TARGET := $(TARGET_NAME)_libretro_qnx.so fpic := -fPIC SHARED := -shared -Wl,--version-script=link.T - CFLAGS += -DHAVE_MMAP + HAVE_MMAP = 1 CC = qcc -Vgcc_ntoarmv7le AR = qcc -Vgcc_ntoarmv7le @@ -122,7 +131,7 @@ else ifeq ($(platform), ps3) TARGET := $(TARGET_NAME)_libretro_ps3.a CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe - CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + CFLAGS += -DMSB_FIRST -D__ppc__ STATIC_LINKING = 1 # sncps3 @@ -130,7 +139,7 @@ else ifeq ($(platform), sncps3) TARGET := $(TARGET_NAME)_libretro_ps3.a CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe - CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + CFLAGS += -DMSB_FIRST -D__ppc__ STATIC_LINKING = 1 # Lightweight PS3 Homebrew SDK @@ -138,7 +147,7 @@ else ifeq ($(platform), psl1ght) TARGET := $(TARGET_NAME)_libretro_psl1ght.a CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) - CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + CFLAGS += -DMSB_FIRST -D__ppc__ STATIC_LINKING = 1 # PSP @@ -162,7 +171,7 @@ else ifeq ($(platform), ngc) TARGET := $(TARGET_NAME)_libretro_ngc.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DMSB_FIRST -D__ppc__ STATIC_LINKING = 1 # Nintendo Wii @@ -170,7 +179,7 @@ else ifeq ($(platform), wii) TARGET := $(TARGET_NAME)_libretro_wii.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DMSB_FIRST -D__ppc__ STATIC_LINKING = 1 # ARM @@ -200,7 +209,7 @@ else ifneq (,$(findstring armv,$(platform))) ASFLAGS += -mfloat-abi=hard endif CFLAGS += -DARM - CFLAGS += -DHAVE_MMAP + HAVE_MMAP = 1 # emscripten else ifeq ($(platform), emscripten) @@ -212,7 +221,16 @@ else CC = gcc SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ -# CFLAGS += -DHAVE_MMAP + +ifeq ($(HAVE_DYNAREC),1) + HAVE_MMAP = 1 + HAVE_MMAP_WIN32 = 1 +endif + +endif + +ifeq ($(HAVE_MMAP), 1) +CFLAGS += -DHAVE_MMAP endif ifeq ($(HAVE_DYNAREC), 1) diff --git a/Makefile.common b/Makefile.common index d7a0c96..1d70835 100644 --- a/Makefile.common +++ b/Makefile.common @@ -29,14 +29,19 @@ endif ifeq ($(CPU_ARCH), arm) SOURCES_ASM += $(CORE_DIR)/arm/arm_stub.S endif - endif ifeq ($(CPU_ARCH), arm) + ifeq ($(CPU_ARCH_ARM_BLENDING_OPTS),1) CFLAGS += -DARM_ARCH_BLENDING_OPTS SOURCES_ASM += $(CORE_DIR)/arm/video_blend.S endif + +endif + +ifeq ($(HAVE_MMAP_WIN32),1) +SOURCES_C += $(CORE_DIR)/memmap_win32.c endif INCFLAGS := -I$(CORE_DIR) diff --git a/libretro.c b/libretro.c index a273265..1ee6dd7 100644 --- a/libretro.c +++ b/libretro.c @@ -6,6 +6,7 @@ #include "common.h" #include "libco.h" #include "libretro.h" +#include "memmap.h" #ifndef MAX_PATH #define MAX_PATH (512) @@ -99,10 +100,6 @@ void retro_get_system_av_info(struct retro_system_av_info* info) info->timing.sample_rate = GBA_SOUND_FREQUENCY; } -#ifdef HAVE_MMAP -#include -#endif - void retro_init(void) { init_gamepak_buffer(); diff --git a/memmap.h b/memmap.h new file mode 100644 index 0000000..e80d720 --- /dev/null +++ b/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/memmap_win32.c b/memmap_win32.c new file mode 100644 index 0000000..f4dbdd6 --- /dev/null +++ b/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; +} + -- cgit v1.2.3