2018-05-21 14:46:03 +00:00
|
|
|
// Copyright 2018 Dolphin Emulator Project
|
|
|
|
// Licensed under GPLv2+
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#include "Common/Debug/MemoryPatches.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <sstream>
|
2018-05-29 22:01:13 +00:00
|
|
|
#include <utility>
|
2018-05-21 14:46:03 +00:00
|
|
|
|
|
|
|
namespace Common::Debug
|
|
|
|
{
|
|
|
|
MemoryPatch::MemoryPatch(u32 address_, std::vector<u8> value_)
|
2018-05-29 22:01:13 +00:00
|
|
|
: address(address_), value(std::move(value_)), is_enabled(State::Enabled)
|
2018-05-21 14:46:03 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryPatch::MemoryPatch(u32 address, u32 value)
|
|
|
|
: MemoryPatch(address, {static_cast<u8>(value >> 24), static_cast<u8>(value >> 16),
|
|
|
|
static_cast<u8>(value >> 8), static_cast<u8>(value)})
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryPatches::MemoryPatches() = default;
|
|
|
|
MemoryPatches::~MemoryPatches() = default;
|
|
|
|
|
|
|
|
void MemoryPatches::SetPatch(u32 address, u32 value)
|
|
|
|
{
|
|
|
|
const std::size_t index = m_patches.size();
|
|
|
|
m_patches.emplace_back(address, value);
|
|
|
|
Patch(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryPatches::SetPatch(u32 address, std::vector<u8> value)
|
|
|
|
{
|
|
|
|
const std::size_t index = m_patches.size();
|
|
|
|
m_patches.emplace_back(address, std::move(value));
|
|
|
|
Patch(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<MemoryPatch>& MemoryPatches::GetPatches() const
|
|
|
|
{
|
|
|
|
return m_patches;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryPatches::UnsetPatch(u32 address)
|
|
|
|
{
|
|
|
|
const auto it = std::remove_if(m_patches.begin(), m_patches.end(),
|
|
|
|
[address](const auto& patch) { return patch.address == address; });
|
|
|
|
|
|
|
|
if (it == m_patches.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const std::size_t size = m_patches.size();
|
|
|
|
std::size_t index = size - std::distance(it, m_patches.end());
|
|
|
|
while (index < size)
|
|
|
|
{
|
|
|
|
DisablePatch(index);
|
|
|
|
++index;
|
|
|
|
}
|
|
|
|
m_patches.erase(it, m_patches.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryPatches::EnablePatch(std::size_t index)
|
|
|
|
{
|
|
|
|
if (m_patches[index].is_enabled == MemoryPatch::State::Enabled)
|
|
|
|
return;
|
|
|
|
m_patches[index].is_enabled = MemoryPatch::State::Enabled;
|
|
|
|
Patch(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryPatches::DisablePatch(std::size_t index)
|
|
|
|
{
|
|
|
|
if (m_patches[index].is_enabled == MemoryPatch::State::Disabled)
|
|
|
|
return;
|
|
|
|
m_patches[index].is_enabled = MemoryPatch::State::Disabled;
|
|
|
|
Patch(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemoryPatches::HasEnabledPatch(u32 address) const
|
|
|
|
{
|
|
|
|
return std::any_of(m_patches.begin(), m_patches.end(), [address](const MemoryPatch& patch) {
|
|
|
|
return patch.address == address && patch.is_enabled == MemoryPatch::State::Enabled;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryPatches::RemovePatch(std::size_t index)
|
|
|
|
{
|
|
|
|
DisablePatch(index);
|
|
|
|
m_patches.erase(m_patches.begin() + index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryPatches::ClearPatches()
|
|
|
|
{
|
|
|
|
const std::size_t size = m_patches.size();
|
|
|
|
for (std::size_t index = 0; index < size; ++index)
|
|
|
|
DisablePatch(index);
|
|
|
|
m_patches.clear();
|
|
|
|
}
|
|
|
|
} // namespace Common::Debug
|