mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 05:09:34 -06:00
Core/CheatSearch: Implement cheat searching functionality.
This commit is contained in:
77
Source/Core/Core/CheatGeneration.cpp
Normal file
77
Source/Core/Core/CheatGeneration.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2021 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "Core/CheatGeneration.h"
|
||||
|
||||
#include "Common/Align.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Result.h"
|
||||
#include "Common/Swap.h"
|
||||
|
||||
#include "Core/ActionReplay.h"
|
||||
#include "Core/CheatSearch.h"
|
||||
|
||||
constexpr int AR_SET_BYTE_CMD = 0x00;
|
||||
constexpr int AR_SET_SHORT_CMD = 0x02;
|
||||
constexpr int AR_SET_INT_CMD = 0x04;
|
||||
|
||||
static std::vector<ActionReplay::AREntry> ResultToAREntries(u32 addr, const Cheats::SearchValue& sv)
|
||||
{
|
||||
std::vector<ActionReplay::AREntry> codes;
|
||||
std::vector<u8> data = Cheats::GetValueAsByteVector(sv);
|
||||
|
||||
for (size_t i = 0; i < data.size(); ++i)
|
||||
{
|
||||
const u32 address = (addr + i) & 0x01ff'ffffu;
|
||||
if (Common::AlignUp(address, 4) == address && i + 3 < data.size())
|
||||
{
|
||||
const u8 cmd = AR_SET_INT_CMD;
|
||||
const u32 val = Common::swap32(&data[i]);
|
||||
codes.emplace_back((cmd << 24) | address, val);
|
||||
i += 3;
|
||||
}
|
||||
else if (Common::AlignUp(address, 2) == address && i + 1 < data.size())
|
||||
{
|
||||
const u8 cmd = AR_SET_SHORT_CMD;
|
||||
const u32 val = Common::swap16(&data[i]);
|
||||
codes.emplace_back((cmd << 24) | address, val);
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u8 cmd = AR_SET_BYTE_CMD;
|
||||
const u32 val = data[i];
|
||||
codes.emplace_back((cmd << 24) | address, val);
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
Common::Result<Cheats::GenerateActionReplayCodeErrorCode, ActionReplay::ARCode>
|
||||
Cheats::GenerateActionReplayCode(const Cheats::CheatSearchSessionBase& session, size_t index)
|
||||
{
|
||||
if (index >= session.GetResultCount())
|
||||
return Cheats::GenerateActionReplayCodeErrorCode::IndexOutOfRange;
|
||||
|
||||
if (session.GetResultValueState(index) != Cheats::SearchResultValueState::ValueFromVirtualMemory)
|
||||
return Cheats::GenerateActionReplayCodeErrorCode::NotVirtualMemory;
|
||||
|
||||
u32 address = session.GetResultAddress(index);
|
||||
|
||||
// check if the address is actually addressable by the ActionReplay system
|
||||
if (((address & 0x01ff'ffffu) | 0x8000'0000u) != address)
|
||||
return Cheats::GenerateActionReplayCodeErrorCode::InvalidAddress;
|
||||
|
||||
ActionReplay::ARCode ar_code;
|
||||
ar_code.enabled = true;
|
||||
ar_code.user_defined = true;
|
||||
ar_code.name = fmt::format("Generated by Cheat Search (Address 0x{:08x})", address);
|
||||
ar_code.ops = ResultToAREntries(address, session.GetResultValueAsSearchValue(index));
|
||||
|
||||
return ar_code;
|
||||
}
|
Reference in New Issue
Block a user