From 0c02e77eee0a12b178b11676ca548aeb1cbb7116 Mon Sep 17 00:00:00 2001 From: Techjar Date: Sun, 28 Apr 2019 04:23:13 -0400 Subject: [PATCH] Core: Remove MemoryWatcher MemoryWatcher only works on Linux and affects emulation determinism due to scheduling additional events, which causes NetPlay to desync. Considering that this interface is a rather specialized use case, the communication with it is kinda crappy *and* it's affecting emulation, I think it's best to just axe it and come up with a better implementation of the functionality. --- CMakeLists.txt | 2 - Source/Core/Common/CommonPaths.h | 5 -- Source/Core/Common/FileUtil.cpp | 6 -- Source/Core/Common/FileUtil.h | 3 - Source/Core/Core/CMakeLists.txt | 4 - Source/Core/Core/Core.cpp | 17 +--- Source/Core/Core/MemoryWatcher.cpp | 130 ----------------------------- Source/Core/Core/MemoryWatcher.h | 47 ----------- 8 files changed, 3 insertions(+), 211 deletions(-) delete mode 100644 Source/Core/Core/MemoryWatcher.cpp delete mode 100644 Source/Core/Core/MemoryWatcher.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 315f75591c..3577234bb5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -481,8 +481,6 @@ endif() if(UNIX) message(STATUS "Using named pipes as controller inputs") add_definitions(-DUSE_PIPES=1) - message(STATUS "Watching game memory for changes") - add_definitions(-DUSE_MEMORYWATCHER=1) endif() if(ENABLE_ANALYTICS) diff --git a/Source/Core/Common/CommonPaths.h b/Source/Core/Common/CommonPaths.h index fe241c5f61..55d2a076c5 100644 --- a/Source/Core/Common/CommonPaths.h +++ b/Source/Core/Common/CommonPaths.h @@ -63,7 +63,6 @@ #define STYLES_DIR "Styles" #define ANAGLYPH_DIR "Anaglyph" #define PIPES_DIR "Pipes" -#define MEMORYWATCHER_DIR "MemoryWatcher" #define WFSROOT_DIR "WFS" #define BACKUP_DIR "Backup" #define RESOURCEPACK_DIR "ResourcePacks" @@ -95,10 +94,6 @@ #define ARAM_DUMP "aram.raw" #define FAKEVMEM_DUMP "fakevmem.raw" -// Files in the directory returned by GetUserPath(D_MEMORYWATCHER_IDX) -#define MEMORYWATCHER_LOCATIONS "Locations.txt" -#define MEMORYWATCHER_SOCKET "MemoryWatcher" - // Sys files #define TOTALDB "totaldb.dsy" diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp index a5d5072929..53f242ecf0 100644 --- a/Source/Core/Common/FileUtil.cpp +++ b/Source/Core/Common/FileUtil.cpp @@ -800,12 +800,6 @@ static void RebuildUserDirectories(unsigned int dir_index) s_user_paths[F_GCSRAM_IDX] = s_user_paths[D_GCUSER_IDX] + GC_SRAM; s_user_paths[F_WIISDCARD_IDX] = s_user_paths[D_WIIROOT_IDX] + DIR_SEP WII_SDCARD; - s_user_paths[D_MEMORYWATCHER_IDX] = s_user_paths[D_USER_IDX] + MEMORYWATCHER_DIR DIR_SEP; - s_user_paths[F_MEMORYWATCHERLOCATIONS_IDX] = - s_user_paths[D_MEMORYWATCHER_IDX] + MEMORYWATCHER_LOCATIONS; - s_user_paths[F_MEMORYWATCHERSOCKET_IDX] = - s_user_paths[D_MEMORYWATCHER_IDX] + MEMORYWATCHER_SOCKET; - // The shader cache has moved to the cache directory, so remove the old one. // TODO: remove that someday. File::DeleteDirRecursively(s_user_paths[D_USER_IDX] + SHADERCACHE_LEGACY_DIR DIR_SEP); diff --git a/Source/Core/Common/FileUtil.h b/Source/Core/Common/FileUtil.h index 6adea032cd..68d6921cdb 100644 --- a/Source/Core/Common/FileUtil.h +++ b/Source/Core/Common/FileUtil.h @@ -48,7 +48,6 @@ enum D_THEMES_IDX, D_STYLES_IDX, D_PIPES_IDX, - D_MEMORYWATCHER_IDX, D_WFSROOT_IDX, D_BACKUP_IDX, D_RESOURCEPACK_IDX, @@ -64,8 +63,6 @@ enum F_ARAMDUMP_IDX, F_FAKEVMEMDUMP_IDX, F_GCSRAM_IDX, - F_MEMORYWATCHERLOCATIONS_IDX, - F_MEMORYWATCHERSOCKET_IDX, F_WIISDCARD_IDX, NUM_PATH_INDICES }; diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 0cda183141..aee4e12a8e 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -379,7 +379,3 @@ endif() if(GDBSTUB) target_sources(core PRIVATE PowerPC/GDBStub.cpp) endif() - -if(UNIX) - target_sources(core PRIVATE MemoryWatcher.cpp) -endif() diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index cf1548314e..9f2f6669f5 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -32,16 +32,11 @@ #include "Common/Timer.h" #include "Core/Analytics.h" +#include "Core/Boot/Boot.h" #include "Core/BootManager.h" #include "Core/ConfigManager.h" #include "Core/CoreTiming.h" #include "Core/DSPEmulator.h" -#include "Core/Host.h" -#include "Core/MemTools.h" -#ifdef USE_MEMORYWATCHER -#include "Core/MemoryWatcher.h" -#endif -#include "Core/Boot/Boot.h" #include "Core/FifoPlayer/FifoPlayer.h" #include "Core/HLE/HLE.h" #include "Core/HW/CPU.h" @@ -53,7 +48,9 @@ #include "Core/HW/SystemTimers.h" #include "Core/HW/VideoInterface.h" #include "Core/HW/Wiimote.h" +#include "Core/Host.h" #include "Core/IOS/IOS.h" +#include "Core/MemTools.h" #include "Core/Movie.h" #include "Core/NetPlayClient.h" #include "Core/NetPlayProto.h" @@ -269,10 +266,6 @@ void Stop() // - Hammertime! } ResetRumble(); - -#ifdef USE_MEMORYWATCHER - MemoryWatcher::Shutdown(); -#endif } void DeclareAsCPUThread() @@ -315,10 +308,6 @@ static void CpuThread(const std::optional& savestate_path, bool del if (_CoreParameter.bFastmem) EMM::InstallExceptionHandler(); // Let's run under memory watch -#ifdef USE_MEMORYWATCHER - MemoryWatcher::Init(); -#endif - if (savestate_path) { ::State::LoadAs(*savestate_path); diff --git a/Source/Core/Core/MemoryWatcher.cpp b/Source/Core/Core/MemoryWatcher.cpp deleted file mode 100644 index e4bd3d0318..0000000000 --- a/Source/Core/Core/MemoryWatcher.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2015 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include -#include -#include -#include -#include - -#include "Common/FileUtil.h" -#include "Core/CoreTiming.h" -#include "Core/HW/Memmap.h" -#include "Core/HW/SystemTimers.h" -#include "Core/MemoryWatcher.h" - -static std::unique_ptr s_memory_watcher; -static CoreTiming::EventType* s_event; -static const int MW_RATE = 600; // Steps per second - -static void MWCallback(u64 userdata, s64 cyclesLate) -{ - s_memory_watcher->Step(); - CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond() / MW_RATE - cyclesLate, s_event); -} - -void MemoryWatcher::Init() -{ - s_memory_watcher = std::make_unique(); - s_event = CoreTiming::RegisterEvent("MemoryWatcher", MWCallback); - CoreTiming::ScheduleEvent(0, s_event); -} - -void MemoryWatcher::Shutdown() -{ - CoreTiming::RemoveEvent(s_event); - s_memory_watcher.reset(); -} - -MemoryWatcher::MemoryWatcher() -{ - m_running = false; - if (!LoadAddresses(File::GetUserPath(F_MEMORYWATCHERLOCATIONS_IDX))) - return; - if (!OpenSocket(File::GetUserPath(F_MEMORYWATCHERSOCKET_IDX))) - return; - m_running = true; -} - -MemoryWatcher::~MemoryWatcher() -{ - if (!m_running) - return; - - m_running = false; - close(m_fd); -} - -bool MemoryWatcher::LoadAddresses(const std::string& path) -{ - std::ifstream locations; - File::OpenFStream(locations, path, std::ios_base::in); - if (!locations) - return false; - - std::string line; - while (std::getline(locations, line)) - ParseLine(line); - - return !m_values.empty(); -} - -void MemoryWatcher::ParseLine(const std::string& line) -{ - m_values[line] = 0; - m_addresses[line] = std::vector(); - - std::stringstream offsets(line); - offsets >> std::hex; - u32 offset; - while (offsets >> offset) - m_addresses[line].push_back(offset); -} - -bool MemoryWatcher::OpenSocket(const std::string& path) -{ - memset(&m_addr, 0, sizeof(m_addr)); - m_addr.sun_family = AF_UNIX; - strncpy(m_addr.sun_path, path.c_str(), sizeof(m_addr.sun_path) - 1); - - m_fd = socket(AF_UNIX, SOCK_DGRAM, 0); - return m_fd >= 0; -} - -u32 MemoryWatcher::ChasePointer(const std::string& line) -{ - u32 value = 0; - for (u32 offset : m_addresses[line]) - value = Memory::Read_U32(value + offset); - return value; -} - -std::string MemoryWatcher::ComposeMessage(const std::string& line, u32 value) -{ - std::stringstream message_stream; - message_stream << line << '\n' << std::hex << value; - return message_stream.str(); -} - -void MemoryWatcher::Step() -{ - if (!m_running) - return; - - for (auto& entry : m_values) - { - std::string address = entry.first; - u32& current_value = entry.second; - - u32 new_value = ChasePointer(address); - if (new_value != current_value) - { - // Update the value - current_value = new_value; - std::string message = ComposeMessage(address, new_value); - sendto(m_fd, message.c_str(), message.size() + 1, 0, reinterpret_cast(&m_addr), - sizeof(m_addr)); - } - } -} diff --git a/Source/Core/Core/MemoryWatcher.h b/Source/Core/Core/MemoryWatcher.h deleted file mode 100644 index e2dc4790bc..0000000000 --- a/Source/Core/Core/MemoryWatcher.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include - -// MemoryWatcher reads a file containing in-game memory addresses and outputs -// changes to those memory addresses to a unix domain socket as the game runs. -// -// The input file is a newline-separated list of hex memory addresses, without -// the "0x". To follow pointers, separate addresses with a space. For example, -// "ABCD EF" will watch the address at (*0xABCD) + 0xEF. -// The output to the socket is two lines. The first is the address from the -// input file, and the second is the new value in hex. -class MemoryWatcher final -{ -public: - MemoryWatcher(); - ~MemoryWatcher(); - void Step(); - - static void Init(); - static void Shutdown(); - -private: - bool LoadAddresses(const std::string& path); - bool OpenSocket(const std::string& path); - - void ParseLine(const std::string& line); - u32 ChasePointer(const std::string& line); - std::string ComposeMessage(const std::string& line, u32 value); - - bool m_running; - - int m_fd; - sockaddr_un m_addr; - - // Address as stored in the file -> list of offsets to follow - std::map> m_addresses; - // Address as stored in the file -> current value - std::map m_values; -};