diff --git a/src/core/gpu.cc b/src/core/gpu.cc index f172be7ee..d139701bb 100644 --- a/src/core/gpu.cc +++ b/src/core/gpu.cc @@ -525,7 +525,7 @@ void PCSX::GPU::dma(uint32_t madr, uint32_t bcr, uint32_t chcr) { // GPU PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %8.8lx addr = %lx size = %lx\n", chcr, madr, bcr); size = gpuDmaChainSize(madr); - chainedDMAWrite((uint32_t *)PCSX::g_emulator->m_mem->m_wram, madr & 0x1fffff); + chainedDMAWrite((uint32_t *)PCSX::g_emulator->m_mem->m_wram.m_mem, madr & 0x1fffff); // Tekken 3 = use 1.0 only (not 1.5x) diff --git a/src/core/mdec.cc b/src/core/mdec.cc index 9e3916997..62e2eb169 100644 --- a/src/core/mdec.cc +++ b/src/core/mdec.cc @@ -371,7 +371,7 @@ void PCSX::MDEC::init(void) { memset(&mdec, 0, sizeof(mdec)); memset(iq_y, 0, sizeof(iq_y)); memset(iq_uv, 0, sizeof(iq_uv)); - mdec.rl = (uint16_t *)&PCSX::g_emulator->m_mem->m_wram[0x100000]; + mdec.rl = (uint16_t *)&PCSX::g_emulator->m_mem->m_wram.m_mem[0x100000]; } // command register diff --git a/src/core/pcsxlua.cc b/src/core/pcsxlua.cc index 8d25ece1c..fbfca9888 100644 --- a/src/core/pcsxlua.cc +++ b/src/core/pcsxlua.cc @@ -34,7 +34,7 @@ struct LuaBreakpoint { PCSX::Debug::BreakpointUserListType wrapper; }; -void* getMemPtr() { return PCSX::g_emulator->m_mem->m_wram; } +void* getMemPtr() { return PCSX::g_emulator->m_mem->m_wram.m_mem; } void* getParPtr() { return PCSX::g_emulator->m_mem->m_exp1; } void* getRomPtr() { return PCSX::g_emulator->m_mem->m_bios; } void* getScratchPtr() { return PCSX::g_emulator->m_mem->m_hard; } diff --git a/src/core/psxemulator.h b/src/core/psxemulator.h index 6288ef9ef..dbb47527f 100644 --- a/src/core/psxemulator.h +++ b/src/core/psxemulator.h @@ -167,7 +167,6 @@ class Emulator { typedef Setting SettingMcd2Inserted; typedef Setting SettingDynarec; typedef Setting Setting8MB; - typedef Setting SettingSharedMemoryMap; typedef Setting SettingGUITheme; typedef Setting SettingDither; typedef Setting SettingCachedDithering; @@ -189,8 +188,8 @@ class Emulator { Settingssettings.get(); - if (memoryMappingEnabled) { - // Create the name of our memory mapping handle which we can search for externally - auto handleName = fmt::format("pcsx-redux-{}", GetCurrentProcessId()); - // Create the memory mapping handle - m_wramFileHandle = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, - static_cast(wramSize), handleName.c_str()); - if (m_wramFileHandle != INVALID_HANDLE_VALUE) { - // Create a view of the memory mapping - void *base_pointer = MapViewOfFileEx(m_wramFileHandle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, - static_cast(wramSize), nullptr); - // Validate success and assign the view to m_wram - if (base_pointer != nullptr) { - doFallbackAlloc = false; - m_wram = (uint8_t *)base_pointer; - } else { - CloseHandle(m_wramFileHandle); - m_wramFileHandle = nullptr; - g_system->message("MapViewOfFileEx failed, falling back to memory alloc, last error: %d\n", - (int)GetLastError()); - } - } else { - m_wramFileHandle = nullptr; - g_system->message("CreateFileMappingA failed, falling back to memory alloc, last error: %d\n", - (int)GetLastError()); - } - } - - if (doFallbackAlloc) { - m_wram = (uint8_t *)calloc(wramSize, 1); - } -#else - m_wram = (uint8_t *)calloc(0x00800000, 1); + uint32_t pid = 0; +#if defined(_WIN32) || defined(_WIN64) + pid = static_cast(GetCurrentProcessId()); +#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) + pid = static_cast(getpid()); #endif + // Init all memory as named mappings + m_wram.init(fmt::format("pcsx-redux-wram-{}", pid).c_str(), 0x00800000); + m_exp1 = (uint8_t *)calloc(0x00800000, 1); m_hard = (uint8_t *)calloc(0x00010000, 1); m_bios = (uint8_t *)calloc(0x00080000, 1); - if (m_readLUT == NULL || m_writeLUT == NULL || m_wram == NULL || m_exp1 == NULL || m_bios == NULL || + if (m_readLUT == NULL || m_writeLUT == NULL || m_wram.m_mem == NULL || m_exp1 == NULL || m_bios == NULL || m_hard == NULL) { g_system->message("%s", _("Error allocating memory!")); return -1; @@ -194,7 +164,7 @@ bool PCSX::Memory::loadEXP1FromFile(std::filesystem::path rom_path) { void PCSX::Memory::reset() { const uint32_t bios_size = 0x00080000; const uint32_t exp1_size = 0x00040000; - memset(m_wram, 0, 0x00800000); + memset(m_wram.m_mem, 0, 0x00800000); memset(m_exp1, 0xff, exp1_size); memset(m_bios, 0, bios_size); static const uint32_t nobios[6] = { @@ -278,21 +248,6 @@ The distributed OpenBIOS.bin file can be an appropriate BIOS replacement. } void PCSX::Memory::shutdown() { -#ifdef _WIN32 - if (m_wramFileHandle != nullptr) { - bool result = static_cast(UnmapViewOfFile(m_wram)); - if (!result) { - g_system->printf("Failed to unmap view of Kernel & User Memory.\n"); - } - m_wram = nullptr; - CloseHandle(m_wramFileHandle); - m_wramFileHandle = nullptr; - } else { - free(m_wram); - } -#else - free(m_wram); -#endif free(m_exp1); free(m_hard); free(m_bios); @@ -701,7 +656,7 @@ const void *PCSX::Memory::pointerWrite(uint32_t address, int size) { void PCSX::Memory::setLuts() { int max = (m_hard[0x1061] & 0x1) ? 0x80 : 0x20; if (!g_emulator->settings.get()) max = 0x20; - for (int i = 0; i < 0x80; i++) m_readLUT[i + 0x0000] = (uint8_t *)&m_wram[(i & (max - 1)) << 16]; + for (int i = 0; i < 0x80; i++) m_readLUT[i + 0x0000] = (uint8_t *)&m_wram.m_mem[(i & (max - 1)) << 16]; memcpy(m_readLUT + 0x8000, m_readLUT, 0x80 * sizeof(void *)); memcpy(m_readLUT + 0xa000, m_readLUT, 0x80 * sizeof(void *)); if (m_writeok) { diff --git a/src/core/psxmem.h b/src/core/psxmem.h index dbfb75a18..f8ad79dc8 100644 --- a/src/core/psxmem.h +++ b/src/core/psxmem.h @@ -23,6 +23,7 @@ #include #include "core/psxemulator.h" +#include "support/sharedmem.h" #if defined(__BIGENDIAN__) @@ -193,7 +194,7 @@ class Memory { // hopefully this should become private eventually, with only certain classes having direct access. public: - uint8_t *m_wram = nullptr; // Kernel & User Memory (8 Meg) + SharedMem m_wram; // Kernel & User Memory (8 Meg) uint8_t *m_exp1 = nullptr; // Expansion Region 1 (ROM/RAM) / Parallel Port (512K) uint8_t *m_bios = nullptr; // BIOS ROM (512K) uint8_t *m_hard = nullptr; // Scratch Pad (1K) & Hardware Registers (8K) diff --git a/src/core/sstate.cc b/src/core/sstate.cc index 6aef5dfb1..d356ba0be 100644 --- a/src/core/sstate.cc +++ b/src/core/sstate.cc @@ -39,7 +39,7 @@ PCSX::SaveStates::SaveState PCSX::SaveStates::constructSaveState() { }, Thumbnail {}, Memory { - RAM { g_emulator->m_mem->m_wram }, + RAM { g_emulator->m_mem->m_wram.m_mem }, ROM { g_emulator->m_mem->m_bios }, EXP1 { g_emulator->m_mem->m_exp1 }, HardwareMemory { g_emulator->m_mem->m_hard }, @@ -242,7 +242,7 @@ void PCSX::GPU::serialize(SaveStateWrapper* w) { void PCSX::MDEC::serialize(SaveStateWrapper* w) { using namespace SaveStates; - uint8_t* base = (uint8_t*)&PCSX::g_emulator->m_mem->m_wram[0x100000]; + uint8_t* base = (uint8_t*)&PCSX::g_emulator->m_mem->m_wram.m_mem[0x100000]; auto& mdecSave = w->state.get(); mdecSave.get().value = mdec.reg0; @@ -402,7 +402,7 @@ void PCSX::GPU::deserialize(const SaveStateWrapper* w) { void PCSX::MDEC::deserialize(const SaveStateWrapper* w) { using namespace SaveStates; - uint8_t* base = (uint8_t*)&g_emulator->m_mem->m_wram[0x100000]; + uint8_t* base = (uint8_t*)&g_emulator->m_mem->m_wram.m_mem[0x100000]; auto& mdecSave = w->state.get(); mdec.reg0 = mdecSave.get().value; diff --git a/src/core/web-server.cc b/src/core/web-server.cc index c0685d963..b0c611645 100644 --- a/src/core/web-server.cc +++ b/src/core/web-server.cc @@ -107,7 +107,7 @@ class RamExecutor : public PCSX::WebExecutor { } uint32_t size = 1024 * 1024 * (ram8M ? 8 : 2); uint8_t* data = (uint8_t*)malloc(size); - memcpy(data, PCSX::g_emulator->m_mem->m_wram, size); + memcpy(data, PCSX::g_emulator->m_mem->m_wram.m_mem, size); PCSX::Slice slice; slice.acquire(data, size); client->write(std::move(slice)); @@ -132,7 +132,7 @@ class RamExecutor : public PCSX::WebExecutor { return true; } - memcpy(PCSX::g_emulator->m_mem->m_wram + offset, request.body.data(), size); + memcpy(PCSX::g_emulator->m_mem->m_wram.m_mem + offset, request.body.data(), size); client->write("HTTP/1.1 200 OK\r\n\r\n"); return true; } diff --git a/src/gui/gui.cc b/src/gui/gui.cc index fda00fb0b..c745d2208 100644 --- a/src/gui/gui.cc +++ b/src/gui/gui.cc @@ -1395,7 +1395,7 @@ in Configuration->Emulation, restart PCSX-Redux, then try again.)")); m_events.draw(g_emulator->m_mem->getMemoryAsFile(), _("Kernel events")); } if (m_handlers.m_show) { - m_handlers.draw(reinterpret_cast(g_emulator->m_mem->m_wram), _("Kernel handlers")); + m_handlers.draw(reinterpret_cast(g_emulator->m_mem->m_wram.m_mem), _("Kernel handlers")); } if (m_kernelLog.m_show) { changed |= m_kernelLog.draw(g_emulator->m_cpu.get(), _("Kernel Calls")); @@ -1410,7 +1410,7 @@ in Configuration->Emulation, restart PCSX-Redux, then try again.)")); if (editor.m_show) { ImGui::SetNextWindowPos(ImVec2(520, 30 + 10 * counter), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(484, 480), ImGuiCond_FirstUseEver); - editor.draw(g_emulator->m_mem->m_wram, 8 * 1024 * 1024); + editor.draw(g_emulator->m_mem->m_wram.m_mem, 8 * 1024 * 1024); } counter++; } @@ -1900,12 +1900,6 @@ this setting may not have any effect for you.)")); ImGuiHelpers::ShowHelpMarker(_(R"(Emulates an installed 8MB system, instead of the normal 2MB. Useful for working with development binaries and games.)")); - changed |= ImGui::Checkbox(_("Shared Memory Map"), &settings.get().value); - ImGuiHelpers::ShowHelpMarker(_(R"(Wraps kernel & user memory in a named memory mapping, -allowing it to be modified from external processes. -Available on Windows platforms only, and requires a restart of the emulator to take effect. -The mapping name is 'pcsx-redux-[process ID]', e.g. 'pcsx-redux-36722'. -See Win32 app documentation for 'Creating Named Shared Memory' for more information.)")); changed |= ImGui::Checkbox(_("OpenGL GPU *ALPHA STATE*"), &settings.get().value); ImGuiHelpers::ShowHelpMarker(_(R"(Enables the OpenGL GPU renderer. diff --git a/src/gui/widgets/assembly.cc b/src/gui/widgets/assembly.cc index 7c998af1d..3ee64b1ee 100644 --- a/src/gui/widgets/assembly.cc +++ b/src/gui/widgets/assembly.cc @@ -573,9 +573,9 @@ settings, otherwise debugging features may not work.)"); const char* section = "UNK"; if (addr < 0x00800000) { section = "RAM"; - code = *reinterpret_cast(m_memory->m_wram + addr); + code = *reinterpret_cast(m_memory->m_wram.m_mem + addr); if (addr <= 0x007ffff8) { - nextCode = *reinterpret_cast(m_memory->m_wram + addr + 4); + nextCode = *reinterpret_cast(m_memory->m_wram.m_mem + addr + 4); } base = m_ramBase; } else if (addr < 0x00810000) { diff --git a/src/gui/widgets/memory_observer.cc b/src/gui/widgets/memory_observer.cc index 3d38db380..720eabc9a 100644 --- a/src/gui/widgets/memory_observer.cc +++ b/src/gui/widgets/memory_observer.cc @@ -37,7 +37,8 @@ PCSX::Widgets::MemoryObserver::MemoryObserver(bool& show) : m_show(show), m_list for (const auto& addressValuePair : m_addressValuePairs) { if (addressValuePair.frozen) { const auto dataSize = getStrideFromValueType(m_scanValueType); - memcpy(g_emulator->m_mem->m_wram + addressValuePair.address - 0x80000000, &addressValuePair.frozenValue, + memcpy(g_emulator->m_mem->m_wram.m_mem + addressValuePair.address - 0x80000000, + &addressValuePair.frozenValue, dataSize); } } @@ -86,7 +87,7 @@ void PCSX::Widgets::MemoryObserver::draw(const char* title) { } if (ImGui::BeginTabBar("SearchTabBar")) { - const uint8_t* const memData = g_emulator->m_mem->m_wram; + const uint8_t* const memData = g_emulator->m_mem->m_wram.m_mem; const uint32_t memSize = 1024 * 1024 * (g_emulator->settings.get() ? 8 : 2); constexpr uint32_t memBase = 0x80000000; diff --git a/src/gui/widgets/typed_debugger.cc b/src/gui/widgets/typed_debugger.cc index 485032ab8..c3d3df769 100644 --- a/src/gui/widgets/typed_debugger.cc +++ b/src/gui/widgets/typed_debugger.cc @@ -158,7 +158,7 @@ PCSX::Widgets::TypedDebugger::TypedDebugger(bool& show) : m_show(show), m_listen m_listener.listen([this](const auto& event) { // When loading a savestate, ensure instructions and functions that have been toggled off are disabled, just in // case they weren't when the savestate was created. - uint8_t* const memData = g_emulator->m_mem->m_wram; + uint8_t* const memData = g_emulator->m_mem->m_wram.m_mem; constexpr uint32_t memBase = 0x80000000; for (const auto& disabledInstruction : m_disabledInstructions) { @@ -222,7 +222,7 @@ static bool isInRAM(uint32_t address) { static uint8_t* getMemoryPointerFor(uint32_t address, uint32_t& outMemBase) { if (isInRAM(address)) { outMemBase = 0x80000000; - return PCSX::g_emulator->m_mem->m_wram; + return PCSX::g_emulator->m_mem->m_wram.m_mem; } const uint32_t memBase = 0x1f800000; @@ -763,7 +763,7 @@ void PCSX::Widgets::TypedDebugger::draw(const char* title, GUI* gui) { ImGui::SameLine(); showReimportButton(_("Reimport functions from updated file"), m_functionsFile, ImportType::Functions); - uint8_t* const memData = g_emulator->m_mem->m_wram; + uint8_t* const memData = g_emulator->m_mem->m_wram.m_mem; const uint32_t memSize = 1024 * 1024 * (g_emulator->settings.get() ? 8 : 2); constexpr uint32_t memBase = 0x80000000; diff --git a/src/main/main.cc b/src/main/main.cc index a964f7ff8..d47f71ba4 100644 --- a/src/main/main.cc +++ b/src/main/main.cc @@ -266,13 +266,6 @@ int pcsxMain(int argc, char **argv) { emuSettings.get() = false; } - if (args.get("sharedmemorymap")) { - emuSettings.get() = true; - } - if (args.get("no-sharedmemorymap")) { - emuSettings.get() = false; - } - if (args.get("fastboot")) { emuSettings.get() = true; } diff --git a/src/support/sharedmem-linux.cc b/src/support/sharedmem-linux.cc new file mode 100644 index 000000000..fccf0362d --- /dev/null +++ b/src/support/sharedmem-linux.cc @@ -0,0 +1,82 @@ +/* + +MIT License + +Copyright (c) 2022 PCSX-Redux authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#ifdef __linux__ + +#include "support/sharedmem.h" +#include "core/system.h" + +#include + +void PCSX::SharedMem::init(const char* name, size_t size) { + assert(m_mem == nullptr); + bool doRawAlloc = true; + // Try to create a shared memory mapping, if a name is provided + m_fd = shm_open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (m_fd < 0) { + g_system->message("shm_open failed, falling back to memory alloc, size: %zu\n", m_size); + } else { + // fd is ready, reserve the memory we need + int result = ftruncate(m_fd, static_cast(size)); + if (result < 0) { + shm_unlink(name); + close(m_fd); + m_fd = -1; + g_system->message("ftruncate failed, falling back to memory alloc, size: %zu\n", m_size); + } else { + // ftruncate completed, now map the memory at 0 offset + void* basePointer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); + // Validate success and assign the view to m_mem + if (basePointer != MAP_FAILED) { + doRawAlloc = false; + m_mem = static_cast(basePointer); + } else { + shm_unlink(name); + close(m_fd); + m_fd = -1; + g_system->message("mmap failed, falling back to memory alloc, size: %zu\n", m_size); + } + } + } + m_name = std::string(name); + m_size = size; + // Alloc memory directly if we opted out or had problems creating the memory map + if (doRawAlloc) { + m_mem = (uint8_t*)calloc(size, 1); + } +} + +PCSX::SharedMem::~SharedMem() { + if (m_fd == -1) { + free(m_mem); + } else { + munmap(m_mem, m_size); + shm_unlink(m_name.c_str()); + close(m_fd); + } +} + +#endif diff --git a/src/support/sharedmem-macos.cc b/src/support/sharedmem-macos.cc new file mode 100644 index 000000000..6ac568c09 --- /dev/null +++ b/src/support/sharedmem-macos.cc @@ -0,0 +1,43 @@ +/* + +MIT License + +Copyright (c) 2022 PCSX-Redux authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#if defined(__APPLE__) && defined(__MACH__) + +#include "support/sharedmem.h" + +#include + +void PCSX::SharedMem::init(const char* name, uint64_t size) { + assert(m_mem == nullptr); + m_size = size; + m_mem = (uint8_t *)calloc(size, 1); +} + +PCSX::SharedMem::~SharedMem() { + free(m_mem); +} + +#endif diff --git a/src/support/sharedmem-windows.cc b/src/support/sharedmem-windows.cc new file mode 100644 index 000000000..61f4c5e62 --- /dev/null +++ b/src/support/sharedmem-windows.cc @@ -0,0 +1,83 @@ +/* + +MIT License + +Copyright (c) 2022 PCSX-Redux authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ +#if defined(_WIN32) || defined(_WIN64) + +#include "support/sharedmem.h" +#include "support/windowswrapper.h" +#include "core/system.h" + +#include + +void PCSX::SharedMem::init(const char* name, size_t size) { + assert(m_mem == nullptr); + bool doRawAlloc = true; + // Try to create a shared memory mapping, if a name is provided + if (name != nullptr) { + // Create the memory mapping handle + m_fileHandle = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, + static_cast(size >> 32), static_cast(size), name); + if (m_fileHandle != INVALID_HANDLE_VALUE) { + // Create a view of the memory mapping at 0 offset + void* basePointer = MapViewOfFileEx(m_fileHandle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size, nullptr); + // Validate success and assign the view to m_mem + if (basePointer != nullptr) { + doRawAlloc = false; + m_mem = static_cast(basePointer); + } else { + CloseHandle(m_fileHandle); + m_fileHandle = nullptr; + g_system->message("MapViewOfFileEx failed, falling back to memory alloc, last error: %d, size: %zu\n", + (int)GetLastError(), m_size); + } + } else { + m_fileHandle = nullptr; + g_system->message("CreateFileMappingA failed, falling back to memory alloc, last error: %d, size: %zu\n", + (int)GetLastError(), m_size); + } + } + + m_size = size; + // Alloc memory directly if we opted out or had problems creating the memory map + if (doRawAlloc) { + m_mem = (uint8_t *)calloc(size, 1); + } +} + +PCSX::SharedMem::~SharedMem() { + if (m_fileHandle != nullptr) { + bool success = static_cast(UnmapViewOfFile(m_mem)); + if (!success) { + g_system->printf("Failed to unmap view of allocated memory (size: %zu).\n", m_size); + } + m_mem = nullptr; + CloseHandle(m_fileHandle); + m_fileHandle = nullptr; + } else { + free(m_mem); + } +} + +#endif diff --git a/src/support/sharedmem.h b/src/support/sharedmem.h new file mode 100644 index 000000000..0348e6d7c --- /dev/null +++ b/src/support/sharedmem.h @@ -0,0 +1,51 @@ +/* + +MIT License + +Copyright (c) 2022 PCSX-Redux authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#pragma once + +#include +#include + +namespace PCSX { + +class SharedMem { + public: + SharedMem() {} + ~SharedMem(); + + void init(const char* name, size_t size); + + public: + uint8_t* m_mem = nullptr; + size_t m_size = 0; + + private: + void* m_fileHandle = nullptr; + std::string m_name; + int m_fd = -1; +}; + +} // namespace PCSX diff --git a/vsprojects/support/support.vcxproj b/vsprojects/support/support.vcxproj index 9d2791fc3..7929e70c9 100644 --- a/vsprojects/support/support.vcxproj +++ b/vsprojects/support/support.vcxproj @@ -301,6 +301,7 @@ + @@ -337,6 +338,9 @@ + + + diff --git a/vsprojects/support/support.vcxproj.filters b/vsprojects/support/support.vcxproj.filters index 3750a30d4..ceb9195c0 100644 --- a/vsprojects/support/support.vcxproj.filters +++ b/vsprojects/support/support.vcxproj.filters @@ -165,6 +165,9 @@ Header Files + + Header Files + @@ -209,6 +212,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files +