Compare commits
1 Commits
cheat_mana
...
cheat_mana
Author | SHA1 | Date | |
---|---|---|---|
012c0b0157 |
@ -588,6 +588,8 @@ add_library(core STATIC
|
|||||||
hle/service/caps/caps_types.h
|
hle/service/caps/caps_types.h
|
||||||
hle/service/caps/caps_u.cpp
|
hle/service/caps/caps_u.cpp
|
||||||
hle/service/caps/caps_u.h
|
hle/service/caps/caps_u.h
|
||||||
|
hle/service/cmif_serialization.h
|
||||||
|
hle/service/cmif_types.h
|
||||||
hle/service/dmnt/cheat_interface.cpp
|
hle/service/dmnt/cheat_interface.cpp
|
||||||
hle/service/dmnt/cheat_interface.h
|
hle/service/dmnt/cheat_interface.h
|
||||||
hle/service/dmnt/cheat_parser.cpp
|
hle/service/dmnt/cheat_parser.cpp
|
||||||
@ -600,8 +602,6 @@ add_library(core STATIC
|
|||||||
hle/service/dmnt/dmnt.h
|
hle/service/dmnt/dmnt.h
|
||||||
hle/service/dmnt/dmnt_results.h
|
hle/service/dmnt/dmnt_results.h
|
||||||
hle/service/dmnt/dmnt_types.h
|
hle/service/dmnt/dmnt_types.h
|
||||||
hle/service/cmif_serialization.h
|
|
||||||
hle/service/cmif_types.h
|
|
||||||
hle/service/erpt/erpt.cpp
|
hle/service/erpt/erpt.cpp
|
||||||
hle/service/erpt/erpt.h
|
hle/service/erpt/erpt.h
|
||||||
hle/service/es/es.cpp
|
hle/service/es/es.cpp
|
||||||
|
@ -362,7 +362,7 @@ struct System::Impl {
|
|||||||
kernel.AppendNewProcess(main_process);
|
kernel.AppendNewProcess(main_process);
|
||||||
kernel.MakeApplicationProcess(main_process);
|
kernel.MakeApplicationProcess(main_process);
|
||||||
|
|
||||||
if (cheat_manager == nullptr) {
|
if (!cheat_manager) {
|
||||||
cheat_manager = std::make_unique<Service::DMNT::CheatProcessManager>(system);
|
cheat_manager = std::make_unique<Service::DMNT::CheatProcessManager>(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,6 +1049,7 @@ Service::DMNT::CheatProcessManager& System::GetCheatManager() {
|
|||||||
const Service::DMNT::CheatProcessManager& System::GetCheatManager() const {
|
const Service::DMNT::CheatProcessManager& System::GetCheatManager() const {
|
||||||
return *impl->cheat_manager;
|
return *impl->cheat_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
Network::RoomNetwork& System::GetRoomNetwork() {
|
Network::RoomNetwork& System::GetRoomNetwork() {
|
||||||
return impl->room_network;
|
return impl->room_network;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ class Controller;
|
|||||||
namespace DMNT {
|
namespace DMNT {
|
||||||
struct CheatEntry;
|
struct CheatEntry;
|
||||||
class CheatProcessManager;
|
class CheatProcessManager;
|
||||||
}
|
} // namespace DMNT
|
||||||
|
|
||||||
namespace FileSystem {
|
namespace FileSystem {
|
||||||
class FileSystemController;
|
class FileSystemController;
|
||||||
|
@ -24,13 +24,13 @@
|
|||||||
#include "core/file_sys/vfs/vfs_cached.h"
|
#include "core/file_sys/vfs/vfs_cached.h"
|
||||||
#include "core/file_sys/vfs/vfs_layered.h"
|
#include "core/file_sys/vfs/vfs_layered.h"
|
||||||
#include "core/file_sys/vfs/vfs_vector.h"
|
#include "core/file_sys/vfs/vfs_vector.h"
|
||||||
|
#include "core/hle/service/dmnt/cheat_parser.h"
|
||||||
|
#include "core/hle/service/dmnt/dmnt_types.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/hle/service/ns/language.h"
|
#include "core/hle/service/ns/language.h"
|
||||||
#include "core/hle/service/set/settings_server.h"
|
#include "core/hle/service/set/settings_server.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "core/loader/nso.h"
|
#include "core/loader/nso.h"
|
||||||
#include "core/hle/service/dmnt/cheat_parser.h"
|
|
||||||
#include "core/hle/service/dmnt/dmnt_types.h"
|
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
namespace {
|
namespace {
|
||||||
@ -512,7 +512,6 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||||||
const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id);
|
const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id);
|
||||||
if (mod_dir != nullptr) {
|
if (mod_dir != nullptr) {
|
||||||
for (const auto& mod : mod_dir->GetSubdirectories()) {
|
for (const auto& mod : mod_dir->GetSubdirectories()) {
|
||||||
std::vector<CheatPatch> cheats;
|
|
||||||
std::string types;
|
std::string types;
|
||||||
|
|
||||||
const auto exefs_dir = FindSubdirectoryCaseless(mod, "exefs");
|
const auto exefs_dir = FindSubdirectoryCaseless(mod, "exefs");
|
||||||
@ -541,32 +540,20 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||||||
}
|
}
|
||||||
if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(mod, "romfs")))
|
if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(mod, "romfs")))
|
||||||
AppendCommaIfNotEmpty(types, "LayeredFS");
|
AppendCommaIfNotEmpty(types, "LayeredFS");
|
||||||
if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(mod, "cheats"))) {
|
if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(mod, "cheats")))
|
||||||
AppendCommaIfNotEmpty(types, "Cheats");
|
AppendCommaIfNotEmpty(types, "Cheats");
|
||||||
cheats.push_back({
|
|
||||||
.enabled = true,
|
|
||||||
.name = "1. Pointed Unit Refill HP/Gas/Ammo (ZL+B)",
|
|
||||||
});
|
|
||||||
cheats.push_back({
|
|
||||||
.enabled = true,
|
|
||||||
.name = "2. Pointed Unit Can Move Again (ZL+B)",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (types.empty())
|
if (types.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto mod_disabled =
|
const auto mod_disabled =
|
||||||
std::find(disabled.begin(), disabled.end(), mod->GetName()) != disabled.end();
|
std::find(disabled.begin(), disabled.end(), mod->GetName()) != disabled.end();
|
||||||
out.push_back({
|
out.push_back({.enabled = !mod_disabled,
|
||||||
.enabled = !mod_disabled,
|
|
||||||
.name = mod->GetName(),
|
.name = mod->GetName(),
|
||||||
.version = types,
|
.version = types,
|
||||||
.type = PatchType::Mod,
|
.type = PatchType::Mod,
|
||||||
.program_id = title_id,
|
.program_id = title_id,
|
||||||
.title_id = title_id,
|
.title_id = title_id});
|
||||||
.cheats = cheats,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,11 +32,6 @@ class NACP;
|
|||||||
|
|
||||||
enum class PatchType { Update, DLC, Mod };
|
enum class PatchType { Update, DLC, Mod };
|
||||||
|
|
||||||
struct CheatPatch {
|
|
||||||
bool enabled;
|
|
||||||
std::string name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Patch {
|
struct Patch {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -44,7 +39,6 @@ struct Patch {
|
|||||||
PatchType type;
|
PatchType type;
|
||||||
u64 program_id;
|
u64 program_id;
|
||||||
u64 title_id;
|
u64 title_id;
|
||||||
std::vector<CheatPatch> cheats;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// A centralized class to manage patches to games.
|
// A centralized class to manage patches to games.
|
||||||
|
@ -60,9 +60,9 @@ Result ICheatInterface::GetCheatProcessEvent(OutCopyHandle<Kernel::KReadableEven
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::GetCheatProcessMetadata(CheatProcessMetadata out_metadata) {
|
Result ICheatInterface::GetCheatProcessMetadata(Out<CheatProcessMetadata> out_metadata) {
|
||||||
LOG_INFO(CheatEngine, "called");
|
LOG_INFO(CheatEngine, "called");
|
||||||
R_RETURN(cheat_process_manager.GetCheatProcessMetadata(out_metadata));
|
R_RETURN(cheat_process_manager.GetCheatProcessMetadata(*out_metadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::ForceOpenCheatProcess() {
|
Result ICheatInterface::ForceOpenCheatProcess() {
|
||||||
@ -82,33 +82,33 @@ Result ICheatInterface::ResumeCheatProcess() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::ForceCloseCheatProcess() {
|
Result ICheatInterface::ForceCloseCheatProcess() {
|
||||||
LOG_INFO(CheatEngine, "called");
|
LOG_WARNING(CheatEngine, "(STUBBED) called");
|
||||||
R_RETURN(cheat_process_manager.ForceCloseCheatProcess());
|
R_RETURN(cheat_process_manager.ForceCloseCheatProcess());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::GetCheatProcessMappingCount(Out<u64> out_count) {
|
Result ICheatInterface::GetCheatProcessMappingCount(Out<u64> out_count) {
|
||||||
LOG_INFO(CheatEngine, "called");
|
LOG_WARNING(CheatEngine, "(STUBBED) called");
|
||||||
R_RETURN(cheat_process_manager.GetCheatProcessMappingCount(*out_count));
|
R_RETURN(cheat_process_manager.GetCheatProcessMappingCount(*out_count));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::GetCheatProcessMappings(
|
Result ICheatInterface::GetCheatProcessMappings(
|
||||||
Out<u64> out_count, u64 offset,
|
Out<u64> out_count, u64 offset,
|
||||||
OutArray<Kernel::Svc::MemoryInfo, BufferAttr_HipcMapAlias> out_mappings) {
|
OutArray<Kernel::Svc::MemoryInfo, BufferAttr_HipcMapAlias> out_mappings) {
|
||||||
LOG_INFO(CheatEngine, "called");
|
LOG_INFO(CheatEngine, "called, offset={}", offset);
|
||||||
R_UNLESS(!out_mappings.empty(), ResultCheatNullBuffer);
|
R_UNLESS(!out_mappings.empty(), ResultCheatNullBuffer);
|
||||||
R_RETURN(cheat_process_manager.GetCheatProcessMappings(*out_count, offset, out_mappings));
|
R_RETURN(cheat_process_manager.GetCheatProcessMappings(*out_count, offset, out_mappings));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::ReadCheatProcessMemory(u64 address, u64 size,
|
Result ICheatInterface::ReadCheatProcessMemory(u64 address, u64 size,
|
||||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer) {
|
OutBuffer<BufferAttr_HipcMapAlias> out_buffer) {
|
||||||
LOG_INFO(CheatEngine, "called");
|
LOG_DEBUG(CheatEngine, "called, address={}, size={}", address, size);
|
||||||
R_UNLESS(!out_buffer.empty(), ResultCheatNullBuffer);
|
R_UNLESS(!out_buffer.empty(), ResultCheatNullBuffer);
|
||||||
R_RETURN(cheat_process_manager.ReadCheatProcessMemory(address, size, out_buffer));
|
R_RETURN(cheat_process_manager.ReadCheatProcessMemory(address, size, out_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::WriteCheatProcessMemory(u64 address, u64 size,
|
Result ICheatInterface::WriteCheatProcessMemory(u64 address, u64 size,
|
||||||
InBuffer<BufferAttr_HipcMapAlias> buffer) {
|
InBuffer<BufferAttr_HipcMapAlias> buffer) {
|
||||||
LOG_INFO(CheatEngine, "called, address={}, size={}", address, size);
|
LOG_DEBUG(CheatEngine, "called, address={}, size={}", address, size);
|
||||||
R_UNLESS(!buffer.empty(), ResultCheatNullBuffer);
|
R_UNLESS(!buffer.empty(), ResultCheatNullBuffer);
|
||||||
R_RETURN(cheat_process_manager.WriteCheatProcessMemory(address, size, buffer));
|
R_RETURN(cheat_process_manager.WriteCheatProcessMemory(address, size, buffer));
|
||||||
}
|
}
|
||||||
@ -155,12 +155,12 @@ Result ICheatInterface::RemoveCheat(u32 cheat_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::ReadStaticRegister(Out<u64> out_value, u8 register_index) {
|
Result ICheatInterface::ReadStaticRegister(Out<u64> out_value, u8 register_index) {
|
||||||
LOG_INFO(CheatEngine, "called, register_index={}", register_index);
|
LOG_DEBUG(CheatEngine, "called, register_index={}", register_index);
|
||||||
R_RETURN(cheat_process_manager.ReadStaticRegister(*out_value, register_index));
|
R_RETURN(cheat_process_manager.ReadStaticRegister(*out_value, register_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::WriteStaticRegister(u64 register_index, u64 value) {
|
Result ICheatInterface::WriteStaticRegister(u8 register_index, u64 value) {
|
||||||
LOG_INFO(CheatEngine, "called, register_index={, value={}", register_index, value);
|
LOG_DEBUG(CheatEngine, "called, register_index={, value={}", register_index, value);
|
||||||
R_RETURN(cheat_process_manager.WriteStaticRegister(register_index, value));
|
R_RETURN(cheat_process_manager.WriteStaticRegister(register_index, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,12 +191,12 @@ Result ICheatInterface::GetFrozenAddresses(
|
|||||||
|
|
||||||
Result ICheatInterface::GetFrozenAddress(Out<FrozenAddressEntry> out_frozen_address_entry,
|
Result ICheatInterface::GetFrozenAddress(Out<FrozenAddressEntry> out_frozen_address_entry,
|
||||||
u64 address) {
|
u64 address) {
|
||||||
LOG_INFO(CheatEngine, "called, adress={}", address);
|
LOG_INFO(CheatEngine, "called, address={}", address);
|
||||||
R_RETURN(cheat_process_manager.GetFrozenAddress(*out_frozen_address_entry, address));
|
R_RETURN(cheat_process_manager.GetFrozenAddress(*out_frozen_address_entry, address));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::EnableFrozenAddress(Out<u64> out_value, u64 address, u64 width) {
|
Result ICheatInterface::EnableFrozenAddress(Out<u64> out_value, u64 address, u64 width) {
|
||||||
LOG_INFO(CheatEngine, "called, adress={}, witdh={}", address, width);
|
LOG_INFO(CheatEngine, "called, address={}, width={}", address, width);
|
||||||
R_UNLESS(width > 0, ResultFrozenAddressInvalidWidth);
|
R_UNLESS(width > 0, ResultFrozenAddressInvalidWidth);
|
||||||
R_UNLESS(width <= sizeof(u64), ResultFrozenAddressInvalidWidth);
|
R_UNLESS(width <= sizeof(u64), ResultFrozenAddressInvalidWidth);
|
||||||
R_UNLESS((width & (width - 1)) == 0, ResultFrozenAddressInvalidWidth);
|
R_UNLESS((width & (width - 1)) == 0, ResultFrozenAddressInvalidWidth);
|
||||||
@ -204,7 +204,7 @@ Result ICheatInterface::EnableFrozenAddress(Out<u64> out_value, u64 address, u64
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::DisableFrozenAddress(u64 address) {
|
Result ICheatInterface::DisableFrozenAddress(u64 address) {
|
||||||
LOG_INFO(CheatEngine, "called, adress={}", address);
|
LOG_INFO(CheatEngine, "called, address={}", address);
|
||||||
R_RETURN(cheat_process_manager.DisableFrozenAddress(address));
|
R_RETURN(cheat_process_manager.DisableFrozenAddress(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,13 +214,13 @@ void ICheatInterface::InitializeCheatManager() {
|
|||||||
|
|
||||||
Result ICheatInterface::ReadCheatProcessMemoryUnsafe(u64 process_addr, std::span<u8> out_data,
|
Result ICheatInterface::ReadCheatProcessMemoryUnsafe(u64 process_addr, std::span<u8> out_data,
|
||||||
size_t size) {
|
size_t size) {
|
||||||
LOG_INFO(CheatEngine, "called");
|
LOG_DEBUG(CheatEngine, "called, process_addr={}, size={}", process_addr, size);
|
||||||
R_RETURN(cheat_process_manager.ReadCheatProcessMemoryUnsafe(process_addr, &out_data, size));
|
R_RETURN(cheat_process_manager.ReadCheatProcessMemoryUnsafe(process_addr, &out_data, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICheatInterface::WriteCheatProcessMemoryUnsafe(u64 process_addr, std::span<const u8> data,
|
Result ICheatInterface::WriteCheatProcessMemoryUnsafe(u64 process_addr, std::span<const u8> data,
|
||||||
size_t size) {
|
size_t size) {
|
||||||
LOG_INFO(CheatEngine, "called");
|
LOG_DEBUG(CheatEngine, "called, process_addr={}, size={}", process_addr, size);
|
||||||
R_RETURN(cheat_process_manager.WriteCheatProcessMemoryUnsafe(process_addr, &data, size));
|
R_RETURN(cheat_process_manager.WriteCheatProcessMemoryUnsafe(process_addr, &data, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Result HasCheatProcess(Out<bool> out_has_cheat);
|
Result HasCheatProcess(Out<bool> out_has_cheat);
|
||||||
Result GetCheatProcessEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
Result GetCheatProcessEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
Result GetCheatProcessMetadata(CheatProcessMetadata out_metadata);
|
Result GetCheatProcessMetadata(Out<CheatProcessMetadata> out_metadata);
|
||||||
Result ForceOpenCheatProcess();
|
Result ForceOpenCheatProcess();
|
||||||
Result PauseCheatProcess();
|
Result PauseCheatProcess();
|
||||||
Result ResumeCheatProcess();
|
Result ResumeCheatProcess();
|
||||||
@ -60,7 +60,7 @@ private:
|
|||||||
InLargeData<CheatDefinition, BufferAttr_HipcMapAlias> cheat_definition);
|
InLargeData<CheatDefinition, BufferAttr_HipcMapAlias> cheat_definition);
|
||||||
Result RemoveCheat(u32 cheat_id);
|
Result RemoveCheat(u32 cheat_id);
|
||||||
Result ReadStaticRegister(Out<u64> out_value, u8 register_index);
|
Result ReadStaticRegister(Out<u64> out_value, u8 register_index);
|
||||||
Result WriteStaticRegister(u64 register_index, u64 value);
|
Result WriteStaticRegister(u8 register_index, u64 value);
|
||||||
Result ResetStaticRegisters();
|
Result ResetStaticRegisters();
|
||||||
Result SetMasterCheat(InLargeData<CheatDefinition, BufferAttr_HipcMapAlias> cheat_definition);
|
Result SetMasterCheat(InLargeData<CheatDefinition, BufferAttr_HipcMapAlias> cheat_definition);
|
||||||
Result GetFrozenAddressCount(Out<u64> out_count);
|
Result GetFrozenAddressCount(Out<u64> out_count);
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "core/hle/service/dmnt/cheat_parser.h"
|
#include "core/hle/service/dmnt/cheat_parser.h"
|
||||||
#include "core/hle/service/dmnt/dmnt_types.h"
|
#include "core/hle/service/dmnt/dmnt_types.h"
|
||||||
|
|
||||||
@ -15,7 +19,7 @@ std::vector<CheatEntry> CheatParser::Parse(std::string_view data) const {
|
|||||||
std::optional<u64> current_entry;
|
std::optional<u64> current_entry;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < data.size(); ++i) {
|
for (std::size_t i = 0; i < data.size(); ++i) {
|
||||||
if (::isspace(data[i])) {
|
if (std::isspace(data[i])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +62,7 @@ std::vector<CheatEntry> CheatParser::Parse(std::string_view data) const {
|
|||||||
'\0';
|
'\0';
|
||||||
|
|
||||||
i += name_size + 1;
|
i += name_size + 1;
|
||||||
} else if (::isxdigit(data[i])) {
|
} else if (std::isxdigit(data[i])) {
|
||||||
if (!current_entry || out[*current_entry].definition.num_opcodes >=
|
if (!current_entry || out[*current_entry].definition.num_opcodes >=
|
||||||
out[*current_entry].definition.opcodes.size()) {
|
out[*current_entry].definition.opcodes.size()) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -44,7 +44,7 @@ void CheatProcessManager::SetVirtualMachine(std::unique_ptr<CheatVirtualMachine>
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CheatProcessManager::HasActiveCheatProcess() {
|
bool CheatProcessManager::HasActiveCheatProcess() {
|
||||||
/* Note: This function *MUST* be called only with the cheat lock held. */
|
// Note: This function *MUST* be called only with the cheat lock held.
|
||||||
bool has_cheat_process =
|
bool has_cheat_process =
|
||||||
cheat_process_debug_handle != InvalidHandle &&
|
cheat_process_debug_handle != InvalidHandle &&
|
||||||
system.ApplicationProcess()->GetProcessId() == cheat_process_metadata.process_id;
|
system.ApplicationProcess()->GetProcessId() == cheat_process_metadata.process_id;
|
||||||
@ -58,28 +58,27 @@ bool CheatProcessManager::HasActiveCheatProcess() {
|
|||||||
|
|
||||||
void CheatProcessManager::CloseActiveCheatProcess() {
|
void CheatProcessManager::CloseActiveCheatProcess() {
|
||||||
if (cheat_process_debug_handle != InvalidHandle) {
|
if (cheat_process_debug_handle != InvalidHandle) {
|
||||||
/* We don't need to do any unsafe breaking. */
|
// We don't need to do any unsafe breaking.
|
||||||
broken_unsafe = false;
|
broken_unsafe = false;
|
||||||
unsafe_break_event->Signal();
|
unsafe_break_event->Signal();
|
||||||
core_timing.UnscheduleEvent(update_event);
|
core_timing.UnscheduleEvent(update_event);
|
||||||
|
|
||||||
/* Close resources. */
|
// Close resources.
|
||||||
// R_ABORT_UNLESS(svc::CloseHandle(cheat_process_debug_handle));
|
|
||||||
cheat_process_debug_handle = InvalidHandle;
|
cheat_process_debug_handle = InvalidHandle;
|
||||||
|
|
||||||
/* Save cheat toggles. */
|
// Save cheat toggles.
|
||||||
if (always_save_cheat_toggles || should_save_cheat_toggles) {
|
if (always_save_cheat_toggles || should_save_cheat_toggles) {
|
||||||
// SaveCheatToggles(cheat_process_metadata.program_id);
|
// TODO: save cheat toggles
|
||||||
should_save_cheat_toggles = false;
|
should_save_cheat_toggles = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear metadata. */
|
// Clear metadata.
|
||||||
cheat_process_metadata = {};
|
cheat_process_metadata = {};
|
||||||
|
|
||||||
/* Clear cheat list. */
|
// Clear cheat list.
|
||||||
ResetAllCheatEntries();
|
ResetAllCheatEntries();
|
||||||
|
|
||||||
/* Clear frozen addresses. */
|
// Clear frozen addresses.
|
||||||
{
|
{
|
||||||
auto it = frozen_addresses_map.begin();
|
auto it = frozen_addresses_map.begin();
|
||||||
while (it != frozen_addresses_map.end()) {
|
while (it != frozen_addresses_map.end()) {
|
||||||
@ -87,7 +86,7 @@ void CheatProcessManager::CloseActiveCheatProcess() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Signal to our fans. */
|
// Signal to our fans.
|
||||||
cheat_process_event->Signal();
|
cheat_process_event->Signal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,18 +119,18 @@ void CheatProcessManager::ResetAllCheatEntries() {
|
|||||||
|
|
||||||
CheatEntry* CheatProcessManager::GetCheatEntryById(size_t i) {
|
CheatEntry* CheatProcessManager::GetCheatEntryById(size_t i) {
|
||||||
if (i < MaxCheatCount) {
|
if (i < MaxCheatCount) {
|
||||||
return cheat_entries + i;
|
return cheat_entries.data() + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheatEntry* CheatProcessManager::GetCheatEntryByReadableName(const char* readable_name) {
|
CheatEntry* CheatProcessManager::GetCheatEntryByReadableName(const char* readable_name) {
|
||||||
/* Check all non-master cheats for match. */
|
// Check all non-master cheats for match.
|
||||||
for (size_t i = 1; i < MaxCheatCount; i++) {
|
for (size_t i = 1; i < MaxCheatCount; i++) {
|
||||||
if (std::strncmp(cheat_entries[i].definition.readable_name.data(), readable_name,
|
if (std::strncmp(cheat_entries[i].definition.readable_name.data(), readable_name,
|
||||||
sizeof(cheat_entries[i].definition.readable_name)) == 0) {
|
sizeof(cheat_entries[i].definition.readable_name)) == 0) {
|
||||||
return cheat_entries + i;
|
return cheat_entries.data() + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,10 +138,10 @@ CheatEntry* CheatProcessManager::GetCheatEntryByReadableName(const char* readabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
CheatEntry* CheatProcessManager::GetFreeCheatEntry() {
|
CheatEntry* CheatProcessManager::GetFreeCheatEntry() {
|
||||||
/* Check all non-master cheats for availability. */
|
// Check all non-master cheats for availability.
|
||||||
for (size_t i = 1; i < MaxCheatCount; i++) {
|
for (size_t i = 1; i < MaxCheatCount; i++) {
|
||||||
if (cheat_entries[i].definition.num_opcodes == 0) {
|
if (cheat_entries[i].definition.num_opcodes == 0) {
|
||||||
return cheat_entries + i;
|
return cheat_entries.data() + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,18 +162,18 @@ Result CheatProcessManager::AttachToApplicationProcess(const std::array<u8, 0x20
|
|||||||
u64 main_region_size) {
|
u64 main_region_size) {
|
||||||
std::scoped_lock lk(cheat_lock);
|
std::scoped_lock lk(cheat_lock);
|
||||||
|
|
||||||
/* Close the active process, if needed. */
|
// Close the active process, if needed.
|
||||||
{
|
{
|
||||||
if (this->HasActiveCheatProcess()) {
|
if (this->HasActiveCheatProcess()) {
|
||||||
/* When forcing attach, we're done. */
|
// When forcing attach, we're done.
|
||||||
this->CloseActiveCheatProcess();
|
this->CloseActiveCheatProcess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the application process's ID. */
|
// Get the application process's ID.
|
||||||
cheat_process_metadata.process_id = system.ApplicationProcess()->GetProcessId();
|
cheat_process_metadata.process_id = system.ApplicationProcess()->GetProcessId();
|
||||||
|
|
||||||
/* Get process handle, use it to learn memory extents. */
|
// Get process handle, use it to learn memory extents.
|
||||||
{
|
{
|
||||||
const auto& page_table = system.ApplicationProcess()->GetPageTable();
|
const auto& page_table = system.ApplicationProcess()->GetPageTable();
|
||||||
cheat_process_metadata.program_id = system.GetApplicationProcessProgramID();
|
cheat_process_metadata.program_id = system.GetApplicationProcessProgramID();
|
||||||
@ -192,7 +191,7 @@ Result CheatProcessManager::AttachToApplicationProcess(const std::array<u8, 0x20
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get module information from loader. */
|
// Get module information from loader.
|
||||||
{
|
{
|
||||||
cheat_process_metadata.main_nso_extents = {
|
cheat_process_metadata.main_nso_extents = {
|
||||||
.base = main_region_begin,
|
.base = main_region_begin,
|
||||||
@ -201,17 +200,17 @@ Result CheatProcessManager::AttachToApplicationProcess(const std::array<u8, 0x20
|
|||||||
cheat_process_metadata.main_nso_build_id = build_id;
|
cheat_process_metadata.main_nso_build_id = build_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set our debug handle. */
|
// Set our debug handle.
|
||||||
cheat_process_debug_handle = cheat_process_metadata.process_id;
|
cheat_process_debug_handle = cheat_process_metadata.process_id;
|
||||||
|
|
||||||
/* Reset broken state. */
|
// Reset broken state.
|
||||||
broken_unsafe = false;
|
broken_unsafe = false;
|
||||||
unsafe_break_event->Signal();
|
unsafe_break_event->Signal();
|
||||||
|
|
||||||
/*start the process. */
|
// start the process.
|
||||||
core_timing.ScheduleLoopingEvent(CHEAT_ENGINE_NS, CHEAT_ENGINE_NS, update_event);
|
core_timing.ScheduleLoopingEvent(CHEAT_ENGINE_NS, CHEAT_ENGINE_NS, update_event);
|
||||||
|
|
||||||
/* Signal to our fans. */
|
// Signal to our fans.
|
||||||
cheat_process_event->Signal();
|
cheat_process_event->Signal();
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -272,22 +271,7 @@ Result CheatProcessManager::GetCheatProcessMappingCount(u64& out_count) {
|
|||||||
std::scoped_lock lk(cheat_lock);
|
std::scoped_lock lk(cheat_lock);
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
// svc::MemoryInfo mem_info;
|
// TODO: Call svc::QueryDebugProcessMemory
|
||||||
// svc::PageInfo page_info;
|
|
||||||
// u64 address = 0, count = 0;
|
|
||||||
// do {
|
|
||||||
// if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mem_info),
|
|
||||||
// std::addressof(page_info),
|
|
||||||
// this->GetCheatProcessHandle(), address))) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (mem_info.permission != svc::MemoryPermission_None) {
|
|
||||||
// count++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// address = mem_info.base_address + mem_info.size;
|
|
||||||
//} while (address != 0);
|
|
||||||
|
|
||||||
out_count = 0;
|
out_count = 0;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -298,25 +282,7 @@ Result CheatProcessManager::GetCheatProcessMappings(
|
|||||||
std::scoped_lock lk(cheat_lock);
|
std::scoped_lock lk(cheat_lock);
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
// svc::MemoryInfo mem_info;
|
// TODO: Call svc::QueryDebugProcessMemory
|
||||||
// svc::PageInfo page_info;
|
|
||||||
// u64 address = 0, total_count = 0, written_count = 0;
|
|
||||||
// do {
|
|
||||||
// if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mem_info),
|
|
||||||
// std::addressof(page_info),
|
|
||||||
// this->GetCheatProcessHandle(), address))) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (mem_info.permission != svc::MemoryPermission_None) {
|
|
||||||
// if (offset <= total_count && written_count < max_count) {
|
|
||||||
// mappings[written_count++] = mem_info;
|
|
||||||
// }
|
|
||||||
// total_count++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// address = mem_info.base_address + mem_info.size;
|
|
||||||
//} while (address != 0 && written_count < max_count);
|
|
||||||
|
|
||||||
out_count = 0;
|
out_count = 0;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -377,14 +343,8 @@ Result CheatProcessManager::GetCheatCount(u64& out_count) {
|
|||||||
std::scoped_lock lk(cheat_lock);
|
std::scoped_lock lk(cheat_lock);
|
||||||
R_TRY(EnsureCheatProcess());
|
R_TRY(EnsureCheatProcess());
|
||||||
|
|
||||||
size_t count = 0;
|
out_count = std::count_if(cheat_entries.begin(), cheat_entries.end(),
|
||||||
for (size_t i = 0; i < MaxCheatCount; i++) {
|
[](const auto& entry) { return entry.definition.num_opcodes != 0; });
|
||||||
if (cheat_entries[i].definition.num_opcodes) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out_count = count;
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,7 +391,7 @@ Result CheatProcessManager::ToggleCheat(u32 cheat_id) {
|
|||||||
|
|
||||||
entry->enabled = !entry->enabled;
|
entry->enabled = !entry->enabled;
|
||||||
|
|
||||||
/* Trigger a VM reload. */
|
// Trigger a VM reload.
|
||||||
SetNeedsReloadVm(true);
|
SetNeedsReloadVm(true);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -451,10 +411,10 @@ Result CheatProcessManager::AddCheat(u32& out_cheat_id, bool enabled,
|
|||||||
new_entry->enabled = enabled;
|
new_entry->enabled = enabled;
|
||||||
new_entry->definition = cheat_definition;
|
new_entry->definition = cheat_definition;
|
||||||
|
|
||||||
/* Trigger a VM reload. */
|
// Trigger a VM reload.
|
||||||
SetNeedsReloadVm(true);
|
SetNeedsReloadVm(true);
|
||||||
|
|
||||||
/* Set output id. */
|
// Set output id.
|
||||||
out_cheat_id = new_entry->cheat_id;
|
out_cheat_id = new_entry->cheat_id;
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -470,7 +430,7 @@ Result CheatProcessManager::RemoveCheat(u32 cheat_id) {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheatProcessManager::ReadStaticRegister(u64& out_value, u8 register_index) {
|
Result CheatProcessManager::ReadStaticRegister(u64& out_value, u64 register_index) {
|
||||||
std::scoped_lock lk(cheat_lock);
|
std::scoped_lock lk(cheat_lock);
|
||||||
R_TRY(EnsureCheatProcess());
|
R_TRY(EnsureCheatProcess());
|
||||||
R_UNLESS(register_index < CheatVirtualMachine::NumStaticRegisters, ResultCheatInvalid);
|
R_UNLESS(register_index < CheatVirtualMachine::NumStaticRegisters, ResultCheatInvalid);
|
||||||
@ -503,12 +463,12 @@ Result CheatProcessManager::SetMasterCheat(const CheatDefinition& cheat_definiti
|
|||||||
R_UNLESS(cheat_definition.num_opcodes != 0, ResultCheatInvalid);
|
R_UNLESS(cheat_definition.num_opcodes != 0, ResultCheatInvalid);
|
||||||
R_UNLESS(cheat_definition.num_opcodes <= cheat_definition.opcodes.size(), ResultCheatInvalid);
|
R_UNLESS(cheat_definition.num_opcodes <= cheat_definition.opcodes.size(), ResultCheatInvalid);
|
||||||
|
|
||||||
CheatEntry* master_entry = cheat_entries + 0;
|
cheat_entries[0] = {
|
||||||
|
.enabled = true,
|
||||||
|
.definition = cheat_definition,
|
||||||
|
};
|
||||||
|
|
||||||
master_entry->enabled = true;
|
// Trigger a VM reload.
|
||||||
master_entry->definition = cheat_definition;
|
|
||||||
|
|
||||||
/* Trigger a VM reload. */
|
|
||||||
SetNeedsReloadVm(true);
|
SetNeedsReloadVm(true);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
@ -67,7 +67,7 @@ public:
|
|||||||
|
|
||||||
Result AddCheat(u32& out_cheat_id, bool enabled, const CheatDefinition& cheat_definition);
|
Result AddCheat(u32& out_cheat_id, bool enabled, const CheatDefinition& cheat_definition);
|
||||||
Result RemoveCheat(u32 cheat_id);
|
Result RemoveCheat(u32 cheat_id);
|
||||||
Result ReadStaticRegister(u64& out_value, u8 register_index);
|
Result ReadStaticRegister(u64& out_value, u64 register_index);
|
||||||
Result WriteStaticRegister(u64 register_index, u64 value);
|
Result WriteStaticRegister(u64 register_index, u64 value);
|
||||||
Result ResetStaticRegisters();
|
Result ResetStaticRegisters();
|
||||||
Result SetMasterCheat(const CheatDefinition& cheat_definition);
|
Result SetMasterCheat(const CheatDefinition& cheat_definition);
|
||||||
@ -111,7 +111,7 @@ private:
|
|||||||
bool enable_cheats_by_default = true;
|
bool enable_cheats_by_default = true;
|
||||||
bool always_save_cheat_toggles = false;
|
bool always_save_cheat_toggles = false;
|
||||||
bool should_save_cheat_toggles = false;
|
bool should_save_cheat_toggles = false;
|
||||||
CheatEntry cheat_entries[MaxCheatCount] = {};
|
std::array<CheatEntry, MaxCheatCount> cheat_entries = {};
|
||||||
// TODO: Replace with IntrusiveRedBlackTree
|
// TODO: Replace with IntrusiveRedBlackTree
|
||||||
std::map<u64, FrozenAddressValue> frozen_addresses_map = {};
|
std::map<u64, FrozenAddressValue> frozen_addresses_map = {};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
#include "core/hle/service/dmnt/cheat_interface.h"
|
#include "core/hle/service/dmnt/cheat_interface.h"
|
||||||
#include "core/hle/service/dmnt/cheat_process_manager.h"
|
#include "core/hle/service/dmnt/cheat_process_manager.h"
|
||||||
#include "core/hle/service/dmnt/cheat_virtual_machine.h"
|
#include "core/hle/service/dmnt/cheat_virtual_machine.h"
|
||||||
|
@ -25,18 +25,19 @@ struct CheatProcessMetadata {
|
|||||||
static_assert(sizeof(CheatProcessMetadata) == 0x70, "CheatProcessMetadata is an invalid size");
|
static_assert(sizeof(CheatProcessMetadata) == 0x70, "CheatProcessMetadata is an invalid size");
|
||||||
|
|
||||||
struct CheatDefinition {
|
struct CheatDefinition {
|
||||||
std::array<char, 0x40> readable_name{};
|
std::array<char, 0x40> readable_name;
|
||||||
u32 num_opcodes{};
|
u32 num_opcodes;
|
||||||
std::array<u32, 0x100> opcodes{};
|
std::array<u32, 0x100> opcodes;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(CheatDefinition) == 0x444, "CheatDefinition is an invalid size");
|
static_assert(sizeof(CheatDefinition) == 0x444, "CheatDefinition is an invalid size");
|
||||||
|
|
||||||
struct CheatEntry {
|
struct CheatEntry {
|
||||||
bool enabled{};
|
bool enabled;
|
||||||
u32 cheat_id{};
|
u32 cheat_id;
|
||||||
CheatDefinition definition{};
|
CheatDefinition definition;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(CheatEntry) == 0x44C, "CheatEntry is an invalid size");
|
static_assert(sizeof(CheatEntry) == 0x44C, "CheatEntry is an invalid size");
|
||||||
|
static_assert(std::is_trivial_v<CheatEntry>, "CheatEntry type must be trivially copyable.");
|
||||||
|
|
||||||
struct FrozenAddressValue {
|
struct FrozenAddressValue {
|
||||||
u64 value;
|
u64 value;
|
||||||
|
@ -59,6 +59,8 @@ ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* p
|
|||||||
|
|
||||||
ui->scrollArea->setLayout(layout);
|
ui->scrollArea->setLayout(layout);
|
||||||
|
|
||||||
|
ui->scrollArea->setEnabled(!system.IsPoweredOn());
|
||||||
|
|
||||||
connect(item_model, &QStandardItemModel::itemChanged,
|
connect(item_model, &QStandardItemModel::itemChanged,
|
||||||
[] { UISettings::values.is_game_list_reload_pending.exchange(true); });
|
[] { UISettings::values.is_game_list_reload_pending.exchange(true); });
|
||||||
}
|
}
|
||||||
@ -126,24 +128,12 @@ void ConfigurePerGameAddons::LoadConfiguration() {
|
|||||||
auto* const first_item = new QStandardItem;
|
auto* const first_item = new QStandardItem;
|
||||||
first_item->setText(name);
|
first_item->setText(name);
|
||||||
first_item->setCheckable(true);
|
first_item->setCheckable(true);
|
||||||
first_item->setEnabled(!system.IsPoweredOn());
|
|
||||||
|
|
||||||
const auto patch_disabled =
|
const auto patch_disabled =
|
||||||
std::find(disabled.begin(), disabled.end(), name.toStdString()) != disabled.end();
|
std::find(disabled.begin(), disabled.end(), name.toStdString()) != disabled.end();
|
||||||
|
|
||||||
first_item->setCheckState(patch_disabled ? Qt::Unchecked : Qt::Checked);
|
first_item->setCheckState(patch_disabled ? Qt::Unchecked : Qt::Checked);
|
||||||
|
|
||||||
for (const auto& cheat : patch.cheats) {
|
|
||||||
auto* const sub_item = new QStandardItem;
|
|
||||||
const auto cheat_name = QString::fromStdString(cheat.name);
|
|
||||||
sub_item->setText(cheat_name);
|
|
||||||
sub_item->setCheckable(true);
|
|
||||||
sub_item->setCheckState(cheat.enabled ? Qt::Checked : Qt::Unchecked);
|
|
||||||
|
|
||||||
first_item->appendRow(sub_item);
|
|
||||||
first_item->setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_items.push_back(QList<QStandardItem*>{
|
list_items.push_back(QList<QStandardItem*>{
|
||||||
first_item, new QStandardItem{QString::fromStdString(patch.version)}});
|
first_item, new QStandardItem{QString::fromStdString(patch.version)}});
|
||||||
item_model->appendRow(list_items.back());
|
item_model->appendRow(list_items.back());
|
||||||
|
Reference in New Issue
Block a user