mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-29 23:32:23 +00:00
dmnt: prevent lag on game thread-spawning
This commit is contained in:
parent
a3d44e37b5
commit
512dbc3a24
3 changed files with 70 additions and 13 deletions
|
@ -22,7 +22,7 @@
|
||||||
#include "pm_shim.h"
|
#include "pm_shim.h"
|
||||||
|
|
||||||
static HosMutex g_cheat_lock;
|
static HosMutex g_cheat_lock;
|
||||||
static HosThread g_detect_thread, g_vm_thread;
|
static HosThread g_detect_thread, g_vm_thread, g_debug_events_thread;
|
||||||
|
|
||||||
static IEvent *g_cheat_process_event;
|
static IEvent *g_cheat_process_event;
|
||||||
static DmntCheatVm *g_cheat_vm;
|
static DmntCheatVm *g_cheat_vm;
|
||||||
|
@ -30,6 +30,12 @@ static DmntCheatVm *g_cheat_vm;
|
||||||
static CheatProcessMetadata g_cheat_process_metadata = {0};
|
static CheatProcessMetadata g_cheat_process_metadata = {0};
|
||||||
static Handle g_cheat_process_debug_hnd = 0;
|
static Handle g_cheat_process_debug_hnd = 0;
|
||||||
|
|
||||||
|
/* For signalling the debug events thread. */
|
||||||
|
static HosSignal g_has_cheat_process_signal;
|
||||||
|
|
||||||
|
/* To save some copying. */
|
||||||
|
static bool g_needs_reload_vm_program = false;
|
||||||
|
|
||||||
/* Global cheat entry storage. */
|
/* Global cheat entry storage. */
|
||||||
static CheatEntry g_cheat_entries[DmntCheatManager::MaxCheatCount];
|
static CheatEntry g_cheat_entries[DmntCheatManager::MaxCheatCount];
|
||||||
|
|
||||||
|
@ -38,6 +44,9 @@ static std::map<u64, FrozenAddressValue> g_frozen_addresses_map;
|
||||||
|
|
||||||
void DmntCheatManager::CloseActiveCheatProcess() {
|
void DmntCheatManager::CloseActiveCheatProcess() {
|
||||||
if (g_cheat_process_debug_hnd != 0) {
|
if (g_cheat_process_debug_hnd != 0) {
|
||||||
|
/* We're no longer in possession of a debug process. */
|
||||||
|
g_has_cheat_process_signal.Reset();
|
||||||
|
|
||||||
/* Close process resources. */
|
/* Close process resources. */
|
||||||
svcCloseHandle(g_cheat_process_debug_hnd);
|
svcCloseHandle(g_cheat_process_debug_hnd);
|
||||||
g_cheat_process_debug_hnd = 0;
|
g_cheat_process_debug_hnd = 0;
|
||||||
|
@ -62,10 +71,6 @@ bool DmntCheatManager::HasActiveCheatProcess() {
|
||||||
has_cheat_process &= R_SUCCEEDED(svcGetProcessId(&tmp, g_cheat_process_debug_hnd));
|
has_cheat_process &= R_SUCCEEDED(svcGetProcessId(&tmp, g_cheat_process_debug_hnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_cheat_process) {
|
|
||||||
has_cheat_process &= R_SUCCEEDED(pmdmntGetApplicationPid(&tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_cheat_process) {
|
if (has_cheat_process) {
|
||||||
has_cheat_process &= tmp == g_cheat_process_metadata.process_id;
|
has_cheat_process &= tmp == g_cheat_process_metadata.process_id;
|
||||||
}
|
}
|
||||||
|
@ -222,6 +227,9 @@ void DmntCheatManager::ResetCheatEntry(size_t i) {
|
||||||
g_cheat_entries[i].enabled = false;
|
g_cheat_entries[i].enabled = false;
|
||||||
g_cheat_entries[i].cheat_id = i;
|
g_cheat_entries[i].cheat_id = i;
|
||||||
g_cheat_entries[i].definition = {0};
|
g_cheat_entries[i].definition = {0};
|
||||||
|
|
||||||
|
/* Trigger a VM reload. */
|
||||||
|
g_needs_reload_vm_program = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,6 +261,9 @@ CheatEntry *DmntCheatManager::GetCheatEntryById(size_t i) {
|
||||||
bool DmntCheatManager::ParseCheats(const char *s, size_t len) {
|
bool DmntCheatManager::ParseCheats(const char *s, size_t len) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
CheatEntry *cur_entry = NULL;
|
CheatEntry *cur_entry = NULL;
|
||||||
|
|
||||||
|
/* Trigger a VM reload. */
|
||||||
|
g_needs_reload_vm_program = true;
|
||||||
|
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
if (isspace(s[i])) {
|
if (isspace(s[i])) {
|
||||||
|
@ -458,6 +469,9 @@ Result DmntCheatManager::ToggleCheat(u32 cheat_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->enabled = !entry->enabled;
|
entry->enabled = !entry->enabled;
|
||||||
|
|
||||||
|
/* Trigger a VM reload. */
|
||||||
|
g_needs_reload_vm_program = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,6 +493,9 @@ Result DmntCheatManager::AddCheat(u32 *out_id, CheatDefinition *def, bool enable
|
||||||
|
|
||||||
new_entry->enabled = enabled;
|
new_entry->enabled = enabled;
|
||||||
new_entry->definition = *def;
|
new_entry->definition = *def;
|
||||||
|
|
||||||
|
/* Trigger a VM reload. */
|
||||||
|
g_needs_reload_vm_program = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,6 +511,9 @@ Result DmntCheatManager::RemoveCheat(u32 cheat_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetCheatEntry(cheat_id);
|
ResetCheatEntry(cheat_id);
|
||||||
|
|
||||||
|
/* Trigger a VM reload. */
|
||||||
|
g_needs_reload_vm_program = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,6 +716,9 @@ Result DmntCheatManager::ForceOpenCheatProcess() {
|
||||||
/* Continue debug events, etc. */
|
/* Continue debug events, etc. */
|
||||||
ContinueCheatProcess();
|
ContinueCheatProcess();
|
||||||
|
|
||||||
|
/* Signal to debug event swallower. */
|
||||||
|
g_has_cheat_process_signal.Signal();
|
||||||
|
|
||||||
/* Signal to our fans. */
|
/* Signal to our fans. */
|
||||||
g_cheat_process_event->Signal();
|
g_cheat_process_event->Signal();
|
||||||
|
|
||||||
|
@ -782,6 +805,9 @@ void DmntCheatManager::OnNewApplicationLaunch() {
|
||||||
/* Continue debug events, etc. */
|
/* Continue debug events, etc. */
|
||||||
ContinueCheatProcess();
|
ContinueCheatProcess();
|
||||||
|
|
||||||
|
/* Signal to debug event swallower. */
|
||||||
|
g_has_cheat_process_signal.Signal();
|
||||||
|
|
||||||
/* Signal to our fans. */
|
/* Signal to our fans. */
|
||||||
g_cheat_process_event->Signal();
|
g_cheat_process_event->Signal();
|
||||||
}
|
}
|
||||||
|
@ -810,11 +836,12 @@ void DmntCheatManager::VmThread(void *arg) {
|
||||||
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
||||||
|
|
||||||
if (HasActiveCheatProcess()) {
|
if (HasActiveCheatProcess()) {
|
||||||
/* Handle any pending debug events. */
|
|
||||||
ContinueCheatProcess();
|
|
||||||
|
|
||||||
/* Execute VM. */
|
/* Execute VM. */
|
||||||
if (g_cheat_vm->LoadProgram(g_cheat_entries, DmntCheatManager::MaxCheatCount)) {
|
if (!g_needs_reload_vm_program || (g_cheat_vm->LoadProgram(g_cheat_entries, DmntCheatManager::MaxCheatCount))) {
|
||||||
|
/* Program: reloaded. */
|
||||||
|
g_needs_reload_vm_program = false;
|
||||||
|
|
||||||
|
/* Execute program if it's present. */
|
||||||
if (g_cheat_vm->GetProgramSize() != 0) {
|
if (g_cheat_vm->GetProgramSize() != 0) {
|
||||||
g_cheat_vm->Execute(&g_cheat_process_metadata);
|
g_cheat_vm->Execute(&g_cheat_process_metadata);
|
||||||
}
|
}
|
||||||
|
@ -826,7 +853,30 @@ void DmntCheatManager::VmThread(void *arg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
svcSleepThread(0x5000000ul);
|
|
||||||
|
constexpr u64 ONE_SECOND = 1000000000ul;
|
||||||
|
constexpr u64 NUM_TIMES = 12;
|
||||||
|
constexpr u64 DELAY = ONE_SECOND / NUM_TIMES;
|
||||||
|
svcSleepThread(DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DmntCheatManager::DebugEventsThread(void *arg) {
|
||||||
|
while (true) {
|
||||||
|
/* Wait to have a cheat process. */
|
||||||
|
g_has_cheat_process_signal.Wait();
|
||||||
|
|
||||||
|
while (g_cheat_process_debug_hnd != 0 && R_SUCCEEDED(svcWaitSynchronizationSingle(g_cheat_process_debug_hnd, U64_MAX))) {
|
||||||
|
{
|
||||||
|
std::scoped_lock<HosMutex> lk(g_cheat_lock);
|
||||||
|
/* Handle any pending debug events. */
|
||||||
|
if (HasActiveCheatProcess()) {
|
||||||
|
ContinueCheatProcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svcSleepThread(1000000ull);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,15 +909,20 @@ void DmntCheatManager::InitializeCheatManager() {
|
||||||
g_cheat_vm = new DmntCheatVm();
|
g_cheat_vm = new DmntCheatVm();
|
||||||
|
|
||||||
/* Spawn application detection thread, spawn cheat vm thread. */
|
/* Spawn application detection thread, spawn cheat vm thread. */
|
||||||
if (R_FAILED(g_detect_thread.Initialize(&DmntCheatManager::DetectThread, nullptr, 0x4000, 28))) {
|
if (R_FAILED(g_detect_thread.Initialize(&DmntCheatManager::DetectThread, nullptr, 0x4000, 39))) {
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
if (R_FAILED(g_vm_thread.Initialize(&DmntCheatManager::VmThread, nullptr, 0x4000, 28))) {
|
|
||||||
|
if (R_FAILED(g_vm_thread.Initialize(&DmntCheatManager::VmThread, nullptr, 0x4000, 48))) {
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(g_debug_events_thread.Initialize(&DmntCheatManager::DebugEventsThread, nullptr, 0x4000, 48))) {
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start threads. */
|
/* Start threads. */
|
||||||
if (R_FAILED(g_detect_thread.Start()) || R_FAILED(g_vm_thread.Start())) {
|
if (R_FAILED(g_detect_thread.Start()) || R_FAILED(g_vm_thread.Start()) || R_FAILED(g_debug_events_thread.Start())) {
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ class DmntCheatManager {
|
||||||
static void OnNewApplicationLaunch();
|
static void OnNewApplicationLaunch();
|
||||||
static void DetectThread(void *arg);
|
static void DetectThread(void *arg);
|
||||||
static void VmThread(void *arg);
|
static void VmThread(void *arg);
|
||||||
|
static void DebugEventsThread(void *arg);
|
||||||
|
|
||||||
static bool HasActiveCheatProcess();
|
static bool HasActiveCheatProcess();
|
||||||
static void CloseActiveCheatProcess();
|
static void CloseActiveCheatProcess();
|
||||||
|
|
|
@ -441,6 +441,7 @@ bool DmntCheatVm::LoadProgram(const CheatEntry *cheats, size_t num_cheats) {
|
||||||
if (cheats[i].enabled) {
|
if (cheats[i].enabled) {
|
||||||
/* Bounds check. */
|
/* Bounds check. */
|
||||||
if (cheats[i].definition.num_opcodes + this->num_opcodes > MaximumProgramOpcodeCount) {
|
if (cheats[i].definition.num_opcodes + this->num_opcodes > MaximumProgramOpcodeCount) {
|
||||||
|
this->num_opcodes = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue