forked from dolphin-emu/dolphin
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This reverts commit 0c02e77.
- Loading branch information
Showing
8 changed files
with
209 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// Copyright 2015 Dolphin Emulator Project | ||
// Licensed under GPLv2+ | ||
// Refer to the license.txt file included. | ||
|
||
#include <fstream> | ||
#include <iostream> | ||
#include <memory> | ||
#include <sstream> | ||
#include <unistd.h> | ||
|
||
#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<MemoryWatcher> 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<MemoryWatcher>(); | ||
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<u32>(); | ||
|
||
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<sockaddr*>(&m_addr), | ||
sizeof(m_addr)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright 2015 Dolphin Emulator Project | ||
// Licensed under GPLv2+ | ||
// Refer to the license.txt file included. | ||
|
||
#pragma once | ||
|
||
#include <map> | ||
#include <sys/socket.h> | ||
#include <sys/un.h> | ||
#include <vector> | ||
|
||
// 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<std::string, std::vector<u32>> m_addresses; | ||
// Address as stored in the file -> current value | ||
std::map<std::string, u32> m_values; | ||
}; |