cdrom: change pause timing again
[pcsx_rearmed.git] / libpcsxcore / memmap_win32.c
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (memmap_win32.c).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include <windows.h>
24 #include <errno.h>
25 #include <io.h>
26
27 #include "memmap.h"
28
29 #ifndef FILE_MAP_EXECUTE
30 #define FILE_MAP_EXECUTE    0x0020
31 #endif /* FILE_MAP_EXECUTE */
32
33 static int __map_mman_error(const DWORD err, const int deferr)
34 {
35     if (err == 0)
36         return 0;
37     /* TODO: implement */
38     return err;
39 }
40
41 static DWORD __map_mmap_prot_page(const int prot)
42 {
43     DWORD protect = 0;
44     
45     if (prot == PROT_NONE)
46         return 0;
47         
48     if ((prot & PROT_EXEC) != 0)
49         protect = ((prot & PROT_WRITE) != 0) ? 
50                     PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
51     else
52         protect = ((prot & PROT_WRITE) != 0) ?
53                     PAGE_READWRITE : PAGE_READONLY;
54     
55     return protect;
56 }
57
58 static DWORD __map_mmap_prot_file(const int prot)
59 {
60     DWORD desiredAccess = 0;
61     
62     if (prot == PROT_NONE)
63         return 0;
64         
65     if ((prot & PROT_READ) != 0)
66         desiredAccess |= FILE_MAP_READ;
67     if ((prot & PROT_WRITE) != 0)
68         desiredAccess |= FILE_MAP_WRITE;
69     if ((prot & PROT_EXEC) != 0)
70         desiredAccess |= FILE_MAP_EXECUTE;
71     
72     return desiredAccess;
73 }
74
75 void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
76 {
77     HANDLE fm, h;
78     
79     void * map = MAP_FAILED;
80     
81 #ifdef _MSC_VER
82 #pragma warning(push)
83 #pragma warning(disable: 4293)
84 #endif
85
86     const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ? 
87                     (DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
88     const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
89                     (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
90     const DWORD protect = __map_mmap_prot_page(prot);
91     const DWORD desiredAccess = __map_mmap_prot_file(prot);
92
93     const off_t maxSize = off + (off_t)len;
94
95     const DWORD dwMaxSizeLow = (sizeof(off_t) <= sizeof(DWORD)) ? 
96                     (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL);
97     const DWORD dwMaxSizeHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
98                     (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL);
99
100 #ifdef _MSC_VER
101 #pragma warning(pop)
102 #endif
103
104     errno = 0;
105     
106     if (len == 0 
107         /* Unsupported flag combinations */
108         || (flags & MAP_FIXED) != 0
109         /* Usupported protection combinations */
110         || prot == PROT_EXEC)
111     {
112         errno = EINVAL;
113         return MAP_FAILED;
114     }
115     
116     h = ((flags & MAP_ANONYMOUS) == 0) ? 
117                     (HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE;
118
119     if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE)
120     {
121         errno = EBADF;
122         return MAP_FAILED;
123     }
124
125     fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL);
126
127     if (!fm)
128        goto error;
129   
130     map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len);
131
132     CloseHandle(fm);
133   
134     if (!map)
135        goto error;
136
137     return map;
138 error:
139     errno = __map_mman_error(GetLastError(), EPERM);
140     return MAP_FAILED;
141 }
142
143 int munmap(void *addr, size_t len)
144 {
145     if (UnmapViewOfFile(addr))
146         return 0;
147         
148     errno =  __map_mman_error(GetLastError(), EPERM);
149     
150     return -1;
151 }
152
153 int mprotect(void *addr, size_t len, int prot)
154 {
155     DWORD newProtect = __map_mmap_prot_page(prot);
156     DWORD oldProtect = 0;
157     
158     if (VirtualProtect(addr, len, newProtect, &oldProtect))
159         return 0;
160     
161     errno =  __map_mman_error(GetLastError(), EPERM);
162     
163     return -1;
164 }
165
166 int msync(void *addr, size_t len, int flags)
167 {
168     if (FlushViewOfFile(addr, len))
169         return 0;
170     
171     errno =  __map_mman_error(GetLastError(), EPERM);
172     
173     return -1;
174 }
175
176 int mlock(const void *addr, size_t len)
177 {
178     if (VirtualLock((LPVOID)addr, len))
179         return 0;
180         
181     errno =  __map_mman_error(GetLastError(), EPERM);
182     
183     return -1;
184 }
185
186 int munlock(const void *addr, size_t len)
187 {
188     if (VirtualUnlock((LPVOID)addr, len))
189         return 0;
190         
191     errno =  __map_mman_error(GetLastError(), EPERM);
192     
193     return -1;
194 }
195