mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-07-10 09:34:40 -06:00
allow coreinit.exit to actually "exit"
fixes #1960 this commit implements one particular approach for exiting emulation when the RPX being emulated calls `coreinit.exit`. I don't believe this might be the best way long term, but it seemed to be the best way given the state (and my knowledge of the codebase). This threads through 'End Emulation' (normally a debug only feature in the Cemu menu) into one more spot in the codebase, when `coreinit.exit` is called. Why did we go this way? Stopping PPC Emulation _while_ the emulator is actively executing an instruction (the call to `coreinit.exit`) seemed like a path of el derado everytime i tried it. calling `Shutdown`, or `ShutdownTitle` is not ideal because it doesn't do things like update status in discord or any of the other window actions, and they lock up because the emulator is already running the coreinit instructions (even if you launch it in a delayed thread, the PPC emulator is still doing stuff). so the only way to get this to somewhat work is _to reach out to the window system_. So I threaded through an `EndEmulation` request, which started off just calling `EndEmulation` that already existed. There is a note on that function about how it memory leaks if called repeatedly, and it's "not finished". However, this seemed better than looping forever, or just crashing with a debug assert. At least you still have a semi-functional window (even if memory is leaking), and a log window you can investigate? However, just calling endemulation didn't exit when Cemu was launched from the command line (my goal), it just returns to the main Cemu window. To make Cemu usable as a command line app that you can fire and forget, I threaded a new variable through, that when end emulation is called and the title was launched with `-g`, or `-t`, it just closes cemu altogether. this allows my CLI commands to "just work"
This commit is contained in:
parent
a3d6395ed7
commit
896c4ab7da
@ -650,22 +650,23 @@ namespace CafeSystem
|
||||
s_implementation = impl;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
cemu_assert_debug(s_initialized);
|
||||
// if a title is running, shut it down
|
||||
if (sSystemRunning)
|
||||
ShutdownTitle();
|
||||
// shutdown persistent subsystems (deprecated manual shutdown)
|
||||
void Shutdown()
|
||||
{
|
||||
if (!s_initialized)
|
||||
return;
|
||||
// if a title is running, shut it down
|
||||
if (sSystemRunning)
|
||||
ShutdownTitle();
|
||||
// shutdown persistent subsystems (deprecated manual shutdown)
|
||||
iosu::odm::Shutdown();
|
||||
iosu::act::Stop();
|
||||
iosu::mcp::Shutdown();
|
||||
iosu::fsa::Shutdown();
|
||||
iosu::mcp::Shutdown();
|
||||
iosu::fsa::Shutdown();
|
||||
// shutdown IOSU modules
|
||||
for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it)
|
||||
(*it)->SystemExit();
|
||||
s_initialized = false;
|
||||
}
|
||||
s_initialized = false;
|
||||
}
|
||||
|
||||
std::string GetInternalVirtualCodeFolder()
|
||||
{
|
||||
@ -1088,6 +1089,12 @@ namespace CafeSystem
|
||||
sSystemRunning = false;
|
||||
}
|
||||
|
||||
void RequestEndTitle(int exitCode)
|
||||
{
|
||||
WindowSystem::SetExitCode(exitCode);
|
||||
WindowSystem::RequestEndCurrentEmulation();
|
||||
}
|
||||
|
||||
/* Virtual mlc storage */
|
||||
|
||||
void InitVirtualMlcStorage()
|
||||
|
||||
@ -23,7 +23,7 @@ namespace CafeSystem
|
||||
|
||||
void Initialize();
|
||||
void SetImplementation(SystemImplementation* impl);
|
||||
void Shutdown();
|
||||
void Shutdown();
|
||||
|
||||
PREPARE_STATUS_CODE PrepareForegroundTitle(TitleId titleId);
|
||||
PREPARE_STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path);
|
||||
@ -45,6 +45,7 @@ namespace CafeSystem
|
||||
CosCapabilityBits GetForegroundTitleCosCapabilities(CosCapabilityGroup group);
|
||||
|
||||
void ShutdownTitle();
|
||||
void RequestEndTitle(int exitCode);
|
||||
|
||||
std::string GetMlcStoragePath(TitleId titleId);
|
||||
void MlcStorageMountAllTitles();
|
||||
|
||||
@ -364,7 +364,7 @@ int BreathOfTheWildChildProcessMain()
|
||||
vkEnumeratePhysicalDevices(instance, &count, nullptr);
|
||||
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
return 0;
|
||||
return WindowSystem::GetExitCode();
|
||||
}
|
||||
|
||||
static void LinuxBreathOfTheWildWorkaround(VkInstance& instance, const VkInstanceCreateInfo* create_info)
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "Common/SysAllocator.h"
|
||||
#include "Cafe/OS/RPL/rpl_symbol_storage.h"
|
||||
|
||||
#include "Cafe/CafeSystem.h"
|
||||
#include "Cafe/OS/libs/coreinit/coreinit_Misc.h"
|
||||
|
||||
// includes for Initialize coreinit submodules
|
||||
@ -241,10 +242,8 @@ namespace coreinit
|
||||
void coreinit_exit(uint32 r)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "The title terminated the process by calling coreinit.exit({})", (sint32)r);
|
||||
DebugLogStackTrace(coreinit::OSGetCurrentThread(), coreinit::OSGetStackPointer());
|
||||
cemu_assert_debug(false);
|
||||
// never return
|
||||
while (true) std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
DebugLogStackTrace(coreinit::OSGetCurrentThread(), coreinit::OSGetStackPointer());
|
||||
CafeSystem::RequestEndTitle((int) r);
|
||||
}
|
||||
|
||||
bool OSIsOffBoot()
|
||||
|
||||
@ -98,6 +98,10 @@ namespace WindowSystem
|
||||
}
|
||||
|
||||
void Create();
|
||||
int GetExitCode();
|
||||
void SetExitCode(int value);
|
||||
|
||||
void RequestEndCurrentEmulation();
|
||||
|
||||
WindowInfo& GetWindowInfo();
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include "wxgui/CemuApp.h"
|
||||
#include "interface/WindowSystem.h"
|
||||
#include "wxCemuConfig.h"
|
||||
#include "wxgui/MainWindow.h"
|
||||
#include "wxgui/wxgui.h"
|
||||
@ -422,9 +423,9 @@ int CemuApp::OnExit()
|
||||
SDLControllerProvider::ShutdownSDL();
|
||||
#endif
|
||||
#if BOOST_OS_WINDOWS
|
||||
ExitProcess(0);
|
||||
ExitProcess(WindowSystem::GetExitCode());
|
||||
#else
|
||||
_Exit(0);
|
||||
_Exit(WindowSystem::GetExitCode());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -161,6 +161,7 @@ enum
|
||||
wxDEFINE_EVENT(wxEVT_SET_WINDOW_TITLE, wxCommandEvent);
|
||||
wxDEFINE_EVENT(wxEVT_REQUEST_GAMELIST_REFRESH, wxCommandEvent);
|
||||
wxDEFINE_EVENT(wxEVT_LAUNCH_GAME, wxLaunchGameEvent);
|
||||
wxDEFINE_EVENT(wxEVT_END_EMULATION, wxEndEmulationEvent);
|
||||
wxDEFINE_EVENT(wxEVT_REQUEST_RECREATE_CANVAS, wxCommandEvent);
|
||||
|
||||
wxBEGIN_EVENT_TABLE(MainWindow, wxFrame)
|
||||
@ -324,11 +325,13 @@ MainWindow::MainWindow()
|
||||
|
||||
if (load_file)
|
||||
{
|
||||
m_launched_bare = true;
|
||||
MainWindow::RequestLaunchGame(load_file.value(), wxLaunchGameEvent::INITIATED_BY::COMMAND_LINE);
|
||||
quick_launch = true;
|
||||
}
|
||||
else if (load_title_id)
|
||||
{
|
||||
m_launched_bare = true;
|
||||
TitleInfo info;
|
||||
TitleId baseId;
|
||||
if (CafeTitleList::FindBaseTitleId(load_title_id.value(), baseId) && CafeTitleList::GetFirstByTitleId(baseId, info))
|
||||
@ -370,6 +373,7 @@ MainWindow::MainWindow()
|
||||
|
||||
Bind(wxEVT_OPEN_GRAPHIC_PACK, &MainWindow::OnGraphicWindowOpen, this);
|
||||
Bind(wxEVT_LAUNCH_GAME, &MainWindow::OnLaunchFromFile, this);
|
||||
Bind(wxEVT_END_EMULATION, &MainWindow::OnEndEmulation, this);
|
||||
|
||||
if (LaunchSettings::GDBStubEnabled())
|
||||
{
|
||||
@ -625,6 +629,34 @@ void MainWindow::OnLaunchFromFile(wxLaunchGameEvent& event)
|
||||
FileLoad(event.GetPath(), event.GetInitiatedBy());
|
||||
}
|
||||
|
||||
void MainWindow::OnEndEmulation(wxEndEmulationEvent& event)
|
||||
{
|
||||
// Game launched with `-g`, or `-t`, no window to return to.
|
||||
if (m_launched_bare)
|
||||
{
|
||||
if (m_debugger_window)
|
||||
{
|
||||
m_debugger_window->CleanupForDestroy();
|
||||
m_debugger_window->Destroy();
|
||||
m_debugger_window = nullptr;
|
||||
}
|
||||
|
||||
if(m_game_list)
|
||||
m_game_list->Close();
|
||||
|
||||
if (!IsMaximized() && !WindowSystem::IsFullScreen())
|
||||
m_restored_size = GetSize();
|
||||
|
||||
SaveSettings();
|
||||
m_timer->Stop();
|
||||
|
||||
CafeSystem::Shutdown();
|
||||
Destroy();
|
||||
}
|
||||
else
|
||||
EndEmulation();
|
||||
}
|
||||
|
||||
void MainWindow::OnFileMenu(wxCommandEvent& event)
|
||||
{
|
||||
const auto menuId = event.GetId();
|
||||
@ -2452,6 +2484,12 @@ void MainWindow::RequestLaunchGame(fs::path filePath, wxLaunchGameEvent::INITIAT
|
||||
wxPostEvent(g_mainFrame, evt);
|
||||
}
|
||||
|
||||
void MainWindow::RequestEndEmulation()
|
||||
{
|
||||
wxEndEmulationEvent evt;
|
||||
wxPostEvent(g_mainFrame, evt);
|
||||
}
|
||||
|
||||
void MainWindow::OnRequestRecreateCanvas(wxCommandEvent& event)
|
||||
{
|
||||
CounterSemaphore* sem = (CounterSemaphore*)event.GetClientData();
|
||||
|
||||
@ -23,8 +23,10 @@ class TitleManager;
|
||||
class GraphicPacksWindow2;
|
||||
class EmulatedUSBDeviceFrame;
|
||||
class wxLaunchGameEvent;
|
||||
class wxEndEmulationEvent;
|
||||
|
||||
wxDECLARE_EVENT(wxEVT_LAUNCH_GAME, wxLaunchGameEvent);
|
||||
wxDECLARE_EVENT(wxEVT_END_EMULATION, wxEndEmulationEvent);
|
||||
wxDECLARE_EVENT(wxEVT_SET_WINDOW_TITLE, wxCommandEvent);
|
||||
|
||||
class wxLaunchGameEvent : public wxCommandEvent
|
||||
@ -52,6 +54,14 @@ private:
|
||||
INITIATED_BY m_initiatedBy;
|
||||
};
|
||||
|
||||
class wxEndEmulationEvent : public wxCommandEvent
|
||||
{
|
||||
public:
|
||||
wxEndEmulationEvent() : wxCommandEvent(wxEVT_END_EMULATION) {}
|
||||
|
||||
wxEvent* Clone() const { return new wxEndEmulationEvent(*this); }
|
||||
};
|
||||
|
||||
class MainWindow : public wxFrame, public CafeSystem::SystemImplementation
|
||||
{
|
||||
friend class CemuApp;
|
||||
@ -132,6 +142,7 @@ public:
|
||||
void OnGesturePan(wxPanGestureEvent& event);
|
||||
|
||||
void OnGameLoaded();
|
||||
void OnEndEmulation(wxEndEmulationEvent& event);
|
||||
|
||||
void AsyncSetTitle(std::string_view windowTitle);
|
||||
|
||||
@ -144,6 +155,7 @@ public:
|
||||
|
||||
static void RequestGameListRefresh();
|
||||
static void RequestLaunchGame(fs::path filePath, wxLaunchGameEvent::INITIATED_BY initiatedBy);
|
||||
static void RequestEndEmulation();
|
||||
|
||||
private:
|
||||
bool FullscreenEnabled() const;
|
||||
@ -176,6 +188,7 @@ private:
|
||||
|
||||
bool m_menu_visible = false;
|
||||
bool m_game_launched = false;
|
||||
bool m_launched_bare = false;
|
||||
|
||||
#ifdef ENABLE_DISCORD_RPC
|
||||
std::unique_ptr<DiscordPresence> m_discord;
|
||||
|
||||
@ -1077,6 +1077,11 @@ void wxGameList::OnColumnResize(wxListEvent& event)
|
||||
void wxGameList::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
Close();
|
||||
}
|
||||
|
||||
void wxGameList::Close()
|
||||
{
|
||||
m_exit = true;
|
||||
}
|
||||
|
||||
|
||||
@ -57,6 +57,7 @@ public:
|
||||
long FindListItemByTitleId(uint64 title_id) const;
|
||||
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void Close();
|
||||
|
||||
private:
|
||||
std::atomic_bool m_exit = false;
|
||||
@ -163,4 +164,3 @@ private:
|
||||
|
||||
static inline std::once_flag s_launch_file_once;
|
||||
};
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
|
||||
WindowSystem::WindowInfo g_window_info{};
|
||||
|
||||
int g_exitCode = 0;
|
||||
std::shared_mutex g_mutex;
|
||||
MainWindow* g_mainFrame = nullptr;
|
||||
|
||||
@ -56,6 +57,21 @@ void WindowSystem::Create()
|
||||
#endif
|
||||
}
|
||||
|
||||
int WindowSystem::GetExitCode()
|
||||
{
|
||||
return g_exitCode;
|
||||
}
|
||||
|
||||
void WindowSystem::SetExitCode(int value)
|
||||
{
|
||||
g_exitCode = value;
|
||||
}
|
||||
|
||||
void WindowSystem::RequestEndCurrentEmulation()
|
||||
{
|
||||
MainWindow::RequestEndEmulation();
|
||||
}
|
||||
|
||||
void WindowSystem::ShowErrorDialog(std::string_view message, std::string_view title, std::optional<WindowSystem::ErrorCategory> /*errorId*/)
|
||||
{
|
||||
wxString caption;
|
||||
|
||||
@ -245,7 +245,7 @@ int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
|
||||
if (!LaunchSettings::HandleCommandline(lpCmdLine))
|
||||
return 0;
|
||||
WindowSystem::Create();
|
||||
return 0;
|
||||
return WindowSystem::GetExitCode();
|
||||
}
|
||||
|
||||
// entrypoint for debug builds with console
|
||||
@ -259,7 +259,7 @@ int main(int argc, char* argv[])
|
||||
if (!LaunchSettings::HandleCommandline(argc, argv))
|
||||
return 0;
|
||||
WindowSystem::Create();
|
||||
return 0;
|
||||
return WindowSystem::GetExitCode();
|
||||
}
|
||||
|
||||
#else
|
||||
@ -278,7 +278,7 @@ int main(int argc, char *argv[])
|
||||
if (!LaunchSettings::HandleCommandline(argc, argv))
|
||||
return 0;
|
||||
WindowSystem::Create();
|
||||
return 0;
|
||||
return WindowSystem::GetExitCode();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user