| 1879 | } |
| 1880 | |
| 1881 | static LPBYTE AllocMemImage(void) |
| 1882 | { |
| 1883 | #ifdef _WIN32 |
| 1884 | LPBYTE baseAddr = NULL; |
| 1885 | |
| 1886 | // Allocate memory for 'memimage' (and the alias 'mem') |
| 1887 | // . Setup so we have 2 consecutive virtual 64K regions pointing to the same physical 64K region. |
| 1888 | // . This is a fix (and optimisation) for 6502 opcodes that do a 16-bit read at 6502 address $FFFF. (GH#1285) |
| 1889 | SYSTEM_INFO info; |
| 1890 | GetSystemInfo(&info); |
| 1891 | bool res = (info.dwAllocationGranularity == _6502_MEM_LEN); |
| 1892 | |
| 1893 | if (res) |
| 1894 | { |
| 1895 | UINT retry = 10; |
| 1896 | do |
| 1897 | { |
| 1898 | res = false; |
| 1899 | const SIZE_T totalVirtualSize = _6502_MEM_LEN * num64KPages; |
| 1900 | baseAddr = (LPBYTE)VirtualAlloc(0, totalVirtualSize, MEM_RESERVE, PAGE_NOACCESS); |
| 1901 | if (baseAddr == NULL) |
| 1902 | break; |
| 1903 | VirtualFree(baseAddr, 0, MEM_RELEASE); |
| 1904 | |
| 1905 | // Create a file mapping object of [64K] size that is backed by the system paging file. |
| 1906 | g_hMemImage = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, _6502_MEM_LEN, NULL); |
| 1907 | // NB. Returns NULL on failure (not INVALID_HANDLE_VALUE) |
| 1908 | if (g_hMemImage == NULL) |
| 1909 | break; |
| 1910 | |
| 1911 | UINT count = 0; |
| 1912 | while (count < num64KPages) |
| 1913 | { |
| 1914 | // MSDN: "To specify a suggested base address for the view, use the MapViewOfFileEx function. However, this practice is not recommended." |
| 1915 | // The OS (ie. another process) may've beaten us to this suggested baseAddr. This is why we retry multiple times. |
| 1916 | if (!MapViewOfFileEx(g_hMemImage, FILE_MAP_ALL_ACCESS, 0, 0, _6502_MEM_LEN, baseAddr + count * _6502_MEM_LEN)) |
| 1917 | break; |
| 1918 | count++; |
| 1919 | } |
| 1920 | |
| 1921 | res = (count == num64KPages); |
| 1922 | if (res) |
| 1923 | break; |
| 1924 | |
| 1925 | // Failed this time, so clean-up and retry... |
| 1926 | FreeMemImage(); |
| 1927 | } |
| 1928 | while (retry--); |
| 1929 | |
| 1930 | #if 1 |
| 1931 | if (res) // test |
| 1932 | { |
| 1933 | baseAddr[0x0000] = 0x11; |
| 1934 | baseAddr[0xffff] = 0x22; |
| 1935 | USHORT value = *((USHORT*)(baseAddr + 0xffff)); |
| 1936 | _ASSERT(value == 0x1122); |
| 1937 | } |
| 1938 | #endif |
no test coverage detected