2018-05-21 08:46:03 -06:00
|
|
|
// Copyright 2018 Dolphin Emulator Project
|
2021-07-04 19:22:19 -06:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2018-05-21 08:46:03 -06:00
|
|
|
|
|
|
|
#include "Common/Debug/MemoryPatches.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <sstream>
|
2018-05-29 16:01:13 -06:00
|
|
|
#include <utility>
|
2018-05-21 08:46:03 -06:00
|
|
|
|
|
|
|
namespace Common::Debug
|
|
|
|
{
|
|
|
|
MemoryPatch::MemoryPatch(u32 address_, std::vector<u8> value_)
|
2018-05-29 16:03:12 -06:00
|
|
|
: address(address_), value(std::move(value_))
|
2018-05-21 08:46:03 -06:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-06-19 19:21:52 -06: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_)})
|
2018-05-21 08:46:03 -06:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryPatches::MemoryPatches() = default;
|
|
|
|
MemoryPatches::~MemoryPatches() = default;
|
|
|
|
|
2023-02-12 03:07:11 -07:00
|
|
|
void MemoryPatches::SetPatch(const Core::CPUThreadGuard& guard, u32 address, u32 value)
|
2018-05-21 08:46:03 -06:00
|
|
|
{
|
|
|
|
const std::size_t index = m_patches.size();
|
|
|
|
m_patches.emplace_back(address, value);
|
2023-02-12 03:07:11 -07:00
|
|
|
Patch(guard, index);
|
2018-05-21 08:46:03 -06:00
|
|
|
}
|
|
|
|
|
2023-02-12 03:07:11 -07:00
|
|
|
void MemoryPatches::SetPatch(const Core::CPUThreadGuard& guard, u32 address, std::vector<u8> value)
|
2018-05-21 08:46:03 -06:00
|
|
|
{
|
2023-02-12 03:07:11 -07:00
|
|
|
UnsetPatch(guard, address);
|
2018-05-21 08:46:03 -06:00
|
|
|
const std::size_t index = m_patches.size();
|
|
|
|
m_patches.emplace_back(address, std::move(value));
|
2023-02-12 03:07:11 -07:00
|
|
|
Patch(guard, index);
|
2018-05-21 08:46:03 -06:00
|
|
|
}
|
|
|
|
|
2023-02-12 03:07:11 -07:00
|
|
|
void MemoryPatches::SetFramePatch(const Core::CPUThreadGuard& guard, u32 address, u32 value)
|
2022-12-22 16:38:08 -07:00
|
|
|
{
|
|
|
|
const std::size_t index = m_patches.size();
|
|
|
|
m_patches.emplace_back(address, value);
|
|
|
|
m_patches.back().type = MemoryPatch::ApplyType::EachFrame;
|
2023-02-12 03:07:11 -07:00
|
|
|
Patch(guard, index);
|
2022-12-22 16:38:08 -07:00
|
|
|
}
|
|
|
|
|
2023-02-12 03:07:11 -07:00
|
|
|
void MemoryPatches::SetFramePatch(const Core::CPUThreadGuard& guard, u32 address,
|
|
|
|
std::vector<u8> value)
|
2022-12-22 16:38:08 -07:00
|
|
|
{
|
2023-02-12 03:07:11 -07:00
|
|
|
UnsetPatch(guard, address);
|
2022-12-22 16:38:08 -07:00
|
|
|
const std::size_t index = m_patches.size();
|
|
|
|
m_patches.emplace_back(address, std::move(value));
|
|
|
|
m_patches.back().type = MemoryPatch::ApplyType::EachFrame;
|
2023-02-12 03:07:11 -07:00
|
|
|
Patch(guard, index);
|
2022-12-22 16:38:08 -07:00
|
|
|
}
|
|
|
|
|
2018-05-21 08:46:03 -06:00
|
|
|
const std::vector<MemoryPatch>& MemoryPatches::GetPatches() const
|
|
|
|
{
|
|
|
|
return m_patches;
|
|
|
|
}
|
|
|
|
|
2023-02-12 03:07:11 -07:00
|
|
|
void MemoryPatches::UnsetPatch(const Core::CPUThreadGuard& guard, u32 address)
|
2018-05-21 08:46:03 -06:00
|
|
|
{
|
2022-10-23 17:41:15 -06:00
|
|
|
const auto it = std::find_if(m_patches.begin(), m_patches.end(),
|
2022-10-23 17:44:12 -06:00
|
|
|
[address](const auto& patch) { return patch.address == address; });
|
2018-05-21 08:46:03 -06:00
|
|
|
|
|
|
|
if (it == m_patches.end())
|
|
|
|
return;
|
|
|
|
|
2022-10-23 17:42:34 -06:00
|
|
|
const std::size_t index = std::distance(m_patches.begin(), it);
|
2023-02-12 03:07:11 -07:00
|
|
|
RemovePatch(guard, index);
|
2018-05-21 08:46:03 -06:00
|
|
|
}
|
|
|
|
|
2023-02-12 03:07:11 -07:00
|
|
|
void MemoryPatches::EnablePatch(const Core::CPUThreadGuard& guard, std::size_t index)
|
2018-05-21 08:46:03 -06:00
|
|
|
{
|
|
|
|
if (m_patches[index].is_enabled == MemoryPatch::State::Enabled)
|
|
|
|
return;
|
|
|
|
m_patches[index].is_enabled = MemoryPatch::State::Enabled;
|
2023-02-12 03:07:11 -07:00
|
|
|
Patch(guard, index);
|
2018-05-21 08:46:03 -06:00
|
|
|
}
|
|
|
|
|
2023-02-12 03:07:11 -07:00
|
|
|
void MemoryPatches::DisablePatch(const Core::CPUThreadGuard& guard, std::size_t index)
|
2018-05-21 08:46:03 -06:00
|
|
|
{
|
|
|
|
if (m_patches[index].is_enabled == MemoryPatch::State::Disabled)
|
|
|
|
return;
|
|
|
|
m_patches[index].is_enabled = MemoryPatch::State::Disabled;
|
2023-02-12 03:07:11 -07:00
|
|
|
Patch(guard, index);
|
2018-05-21 08:46:03 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-02-12 03:07:11 -07:00
|
|
|
void MemoryPatches::RemovePatch(const Core::CPUThreadGuard& guard, std::size_t index)
|
2018-05-21 08:46:03 -06:00
|
|
|
{
|
2023-02-12 03:07:11 -07:00
|
|
|
DisablePatch(guard, index);
|
2022-12-22 16:38:08 -07:00
|
|
|
UnPatch(index);
|
2018-05-21 08:46:03 -06:00
|
|
|
m_patches.erase(m_patches.begin() + index);
|
|
|
|
}
|
|
|
|
|
2023-02-12 03:07:11 -07:00
|
|
|
void MemoryPatches::ClearPatches(const Core::CPUThreadGuard& guard)
|
2018-05-21 08:46:03 -06:00
|
|
|
{
|
|
|
|
const std::size_t size = m_patches.size();
|
|
|
|
for (std::size_t index = 0; index < size; ++index)
|
2022-12-22 16:38:08 -07:00
|
|
|
{
|
2023-02-12 03:07:11 -07:00
|
|
|
DisablePatch(guard, index);
|
2022-12-22 16:38:08 -07:00
|
|
|
UnPatch(index);
|
|
|
|
}
|
2018-05-21 08:46:03 -06:00
|
|
|
m_patches.clear();
|
|
|
|
}
|
|
|
|
} // namespace Common::Debug
|