dmnt-cheat: Fix debug event management

This commit is contained in:
Michael Scire 2019-03-05 23:58:36 -08:00
parent 512dbc3a24
commit 4d0ab41e6e
3 changed files with 65 additions and 39 deletions

View file

@ -30,8 +30,9 @@ 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. */ /* For debug event thread management. */
static HosSignal g_has_cheat_process_signal; static HosMutex g_debug_event_thread_lock;
static bool g_has_debug_events_thread = false;
/* To save some copying. */ /* To save some copying. */
static bool g_needs_reload_vm_program = false; static bool g_needs_reload_vm_program = false;
@ -42,11 +43,39 @@ static CheatEntry g_cheat_entries[DmntCheatManager::MaxCheatCount];
/* Global frozen address storage. */ /* Global frozen address storage. */
static std::map<u64, FrozenAddressValue> g_frozen_addresses_map; static std::map<u64, FrozenAddressValue> g_frozen_addresses_map;
void DmntCheatManager::StartDebugEventsThread() {
std::scoped_lock<HosMutex> lk(g_debug_event_thread_lock);
/* Spawn the debug events thread. */
if (!g_has_debug_events_thread) {
Result rc;
if (R_FAILED((rc = g_debug_events_thread.Initialize(&DmntCheatManager::DebugEventsThread, nullptr, 0x4000, 48)))) {
return fatalSimple(rc);
}
if (R_FAILED((rc = g_debug_events_thread.Start()))) {
return fatalSimple(rc);
}
g_has_debug_events_thread = true;
}
}
void DmntCheatManager::WaitDebugEventsThread() {
std::scoped_lock<HosMutex> lk(g_debug_event_thread_lock);
/* Wait for the thread to exit. */
if (g_has_debug_events_thread) {
g_debug_events_thread.CancelSynchronization();
g_debug_events_thread.Join();
g_has_debug_events_thread = false;
}
}
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;
@ -71,6 +100,10 @@ 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;
} }
@ -652,6 +685,11 @@ Result DmntCheatManager::ForceOpenCheatProcess() {
return 0; return 0;
} }
/* Close the current application, if it's open. */
CloseActiveCheatProcess();
/* Wait to not have debug events thread. */
WaitDebugEventsThread();
/* Get the current application process ID. */ /* Get the current application process ID. */
if (R_FAILED((rc = pmdmntGetApplicationPid(&g_cheat_process_metadata.process_id)))) { if (R_FAILED((rc = pmdmntGetApplicationPid(&g_cheat_process_metadata.process_id)))) {
return rc; return rc;
@ -713,11 +751,8 @@ Result DmntCheatManager::ForceOpenCheatProcess() {
return rc; return rc;
} }
/* Continue debug events, etc. */ /* Start debug events thread. */
ContinueCheatProcess(); StartDebugEventsThread();
/* 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();
@ -732,6 +767,9 @@ void DmntCheatManager::OnNewApplicationLaunch() {
/* Close the current application, if it's open. */ /* Close the current application, if it's open. */
CloseActiveCheatProcess(); CloseActiveCheatProcess();
/* Wait to not have debug events thread. */
WaitDebugEventsThread();
/* Get the new application's process ID. */ /* Get the new application's process ID. */
if (R_FAILED((rc = pmdmntGetApplicationPid(&g_cheat_process_metadata.process_id)))) { if (R_FAILED((rc = pmdmntGetApplicationPid(&g_cheat_process_metadata.process_id)))) {
fatalSimple(rc); fatalSimple(rc);
@ -802,11 +840,8 @@ void DmntCheatManager::OnNewApplicationLaunch() {
/* Start the process. */ /* Start the process. */
StartDebugProcess(g_cheat_process_metadata.process_id); StartDebugProcess(g_cheat_process_metadata.process_id);
/* Continue debug events, etc. */ /* Start debug events thread. */
ContinueCheatProcess(); StartDebugEventsThread();
/* 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();
@ -862,22 +897,14 @@ void DmntCheatManager::VmThread(void *arg) {
} }
void DmntCheatManager::DebugEventsThread(void *arg) { void DmntCheatManager::DebugEventsThread(void *arg) {
while (true) { while (R_SUCCEEDED(svcWaitSynchronizationSingle(g_cheat_process_debug_hnd, U64_MAX))) {
/* 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); std::scoped_lock<HosMutex> lk(g_cheat_lock);
/* Handle any pending debug events. */ /* Handle any pending debug events. */
if (HasActiveCheatProcess()) { if (HasActiveCheatProcess()) {
ContinueCheatProcess(); ContinueCheatProcess();
} }
} }
svcSleepThread(1000000ull);
}
}
} }
bool DmntCheatManager::GetHasActiveCheatProcess() { bool DmntCheatManager::GetHasActiveCheatProcess() {
@ -917,12 +944,8 @@ void DmntCheatManager::InitializeCheatManager() {
std::abort(); std::abort();
} }
if (R_FAILED(g_debug_events_thread.Initialize(&DmntCheatManager::DebugEventsThread, nullptr, 0x4000, 48))) {
std::abort();
}
/* Start threads. */ /* Start threads. */
if (R_FAILED(g_detect_thread.Start()) || R_FAILED(g_vm_thread.Start()) || R_FAILED(g_debug_events_thread.Start())) { if (R_FAILED(g_detect_thread.Start()) || R_FAILED(g_vm_thread.Start())) {
std::abort(); std::abort();
} }
} }

View file

@ -31,6 +31,9 @@ class DmntCheatManager {
static void VmThread(void *arg); static void VmThread(void *arg);
static void DebugEventsThread(void *arg); static void DebugEventsThread(void *arg);
static void StartDebugEventsThread();
static void WaitDebugEventsThread();
static bool HasActiveCheatProcess(); static bool HasActiveCheatProcess();
static void CloseActiveCheatProcess(); static void CloseActiveCheatProcess();
static void ContinueCheatProcess(); static void ContinueCheatProcess();

@ -1 +1 @@
Subproject commit 0fbc0e2f468762de62d2b14d6495247d04e80bc3 Subproject commit 49d2188f6fb71b54532f089a2c9439665a327ccd