diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index 0d065b8..4b22df6 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -67,6 +67,11 @@ set(SWA_KERNEL_CXX_SOURCES "kernel/io/file_system.cpp" ) +set(SWA_OS_CXX_SOURCES + "os/win32/process_win32.cpp" + "os/process.cpp" +) + set(SWA_CPU_CXX_SOURCES "cpu/guest_thread.cpp" "cpu/code_cache.cpp" @@ -163,6 +168,7 @@ set(SWA_CXX_SOURCES "stdafx.cpp" ${SWA_KERNEL_CXX_SOURCES} + ${SWA_OS_CXX_SOURCES} ${SWA_CPU_CXX_SOURCES} ${SWA_GPU_CXX_SOURCES} ${SWA_APU_CXX_SOURCES} diff --git a/UnleashedRecomp/app.cpp b/UnleashedRecomp/app.cpp index a317d28..aa0daaa 100644 --- a/UnleashedRecomp/app.cpp +++ b/UnleashedRecomp/app.cpp @@ -3,18 +3,24 @@ #include #include #include +#include -bool g_isAppInit = false; -bool g_isMissingDLC = false; +void App::Exit(std::vector restartArgs) +{ + if (restartArgs.size()) + os::process::StartProcess(os::process::GetExecutablePath(), restartArgs, os::process::GetWorkingDirectory()); -double g_deltaTime; +#if _WIN32 + ExitProcess(0); +#endif +} // CApplication::Ctor PPC_FUNC_IMPL(__imp__sub_824EB490); PPC_FUNC(sub_824EB490) { - g_isAppInit = true; - g_isMissingDLC = !Installer::checkAllDLC(GetGamePath()); + App::s_isInit = true; + App::s_isMissingDLC = !Installer::checkAllDLC(GetGamePath()); __imp__sub_824EB490(ctx, base); } @@ -23,13 +29,13 @@ PPC_FUNC(sub_824EB490) PPC_FUNC_IMPL(__imp__sub_822C1130); PPC_FUNC(sub_822C1130) { - g_deltaTime = ctx.f1.f64; + App::s_deltaTime = ctx.f1.f64; SDL_PumpEvents(); SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); Window::Update(); - AudioPatches::Update(g_deltaTime); + AudioPatches::Update(App::s_deltaTime); __imp__sub_822C1130(ctx, base); } diff --git a/UnleashedRecomp/app.h b/UnleashedRecomp/app.h index 4932a41..89849a6 100644 --- a/UnleashedRecomp/app.h +++ b/UnleashedRecomp/app.h @@ -1,6 +1,12 @@ #pragma once -extern bool g_isAppInit; -extern bool g_isMissingDLC; +class App +{ +public: + inline static bool s_isInit; + inline static bool s_isMissingDLC; -extern double g_deltaTime; + inline static double s_deltaTime; + + static void Exit(std::vector restartArgs = {}); +}; diff --git a/UnleashedRecomp/gpu/imgui_snapshot.cpp b/UnleashedRecomp/gpu/imgui_snapshot.cpp index 0c5f5f6..6714906 100644 --- a/UnleashedRecomp/gpu/imgui_snapshot.cpp +++ b/UnleashedRecomp/gpu/imgui_snapshot.cpp @@ -222,7 +222,7 @@ void ImFontAtlasSnapshot::GenerateGlyphRanges() } } - if (g_isAppInit) + if (App::s_isInit) { for (size_t i = XDBF_LANGUAGE_ENGLISH; i <= XDBF_LANGUAGE_ITALIAN; i++) { diff --git a/UnleashedRecomp/os/.gitignore b/UnleashedRecomp/os/.gitignore new file mode 100644 index 0000000..a049fed --- /dev/null +++ b/UnleashedRecomp/os/.gitignore @@ -0,0 +1 @@ +![Ww][Ii][Nn]32/ \ No newline at end of file diff --git a/UnleashedRecomp/os/process.cpp b/UnleashedRecomp/os/process.cpp new file mode 100644 index 0000000..68b06d7 --- /dev/null +++ b/UnleashedRecomp/os/process.cpp @@ -0,0 +1,17 @@ +#include "process.h" +#include "process_detail.h" + +std::filesystem::path os::process::GetExecutablePath() +{ + return detail::GetExecutablePath(); +} + +std::filesystem::path os::process::GetWorkingDirectory() +{ + return detail::GetWorkingDirectory(); +} + +bool os::process::StartProcess(const std::filesystem::path path, const std::vector args, std::filesystem::path work) +{ + return detail::StartProcess(path, args, work); +} diff --git a/UnleashedRecomp/os/process.h b/UnleashedRecomp/os/process.h new file mode 100644 index 0000000..d9af717 --- /dev/null +++ b/UnleashedRecomp/os/process.h @@ -0,0 +1,8 @@ +#pragma once + +namespace os::process +{ + std::filesystem::path GetExecutablePath(); + std::filesystem::path GetWorkingDirectory(); + bool StartProcess(const std::filesystem::path path, const std::vector args, std::filesystem::path work = {}); +} diff --git a/UnleashedRecomp/os/process_detail.h b/UnleashedRecomp/os/process_detail.h new file mode 100644 index 0000000..e4a7a45 --- /dev/null +++ b/UnleashedRecomp/os/process_detail.h @@ -0,0 +1,8 @@ +#pragma once + +namespace os::process::detail +{ + std::filesystem::path GetExecutablePath(); + std::filesystem::path GetWorkingDirectory(); + bool StartProcess(const std::filesystem::path path, const std::vector args, std::filesystem::path work = {}); +} diff --git a/UnleashedRecomp/os/win32/process_win32.cpp b/UnleashedRecomp/os/win32/process_win32.cpp new file mode 100644 index 0000000..147127a --- /dev/null +++ b/UnleashedRecomp/os/win32/process_win32.cpp @@ -0,0 +1,45 @@ +#include + +std::filesystem::path os::process::detail::GetExecutablePath() +{ + char exePath[MAX_PATH]; + + if (!GetModuleFileNameA(nullptr, exePath, MAX_PATH)) + return std::filesystem::path(); + + return std::filesystem::path(exePath); +} + +std::filesystem::path os::process::detail::GetWorkingDirectory() +{ + char workPath[MAX_PATH]; + + if (!GetCurrentDirectoryA(MAX_PATH, workPath)) + return std::filesystem::path(); + + return std::filesystem::path(workPath); +} + +bool os::process::detail::StartProcess(const std::filesystem::path path, const std::vector args, std::filesystem::path work) +{ + if (path.empty()) + return false; + + if (work.empty()) + work = path.parent_path(); + + auto cli = path.string(); + for (auto& arg : args) + cli += " " + arg; + + STARTUPINFOA startInfo{ sizeof(STARTUPINFOA) }; + PROCESS_INFORMATION procInfo{}; + + if (!CreateProcessA(path.string().c_str(), cli.data(), nullptr, nullptr, false, 0, nullptr, work.string().c_str(), &startInfo, &procInfo)) + return false; + + CloseHandle(procInfo.hProcess); + CloseHandle(procInfo.hThread); + + return true; +} diff --git a/UnleashedRecomp/patches/fps_patches.cpp b/UnleashedRecomp/patches/fps_patches.cpp index 289fea5..f6f2c6b 100644 --- a/UnleashedRecomp/patches/fps_patches.cpp +++ b/UnleashedRecomp/patches/fps_patches.cpp @@ -41,12 +41,12 @@ static double ComputeLerpFactor(double t, double deltaTime) // delta time, as it might be time scaled and not match with 30 FPS behavior. void CameraLerpFixMidAsmHook(PPCRegister& t) { - t.f64 = ComputeLerpFactor(t.f64, g_deltaTime); + t.f64 = ComputeLerpFactor(t.f64, App::s_deltaTime); } void CameraTargetSideOffsetLerpFixMidAsmHook(PPCVRegister& v13, PPCVRegister& v62) { - float factor = float(ComputeLerpFactor(double(v13.f32[0] * v62.f32[0]), g_deltaTime)); + float factor = float(ComputeLerpFactor(double(v13.f32[0] * v62.f32[0]), App::s_deltaTime)); for (size_t i = 0; i < 4; i++) { diff --git a/UnleashedRecomp/patches/ui/CHudPause_patches.cpp b/UnleashedRecomp/patches/ui/CHudPause_patches.cpp index 9e57e6d..4627389 100644 --- a/UnleashedRecomp/patches/ui/CHudPause_patches.cpp +++ b/UnleashedRecomp/patches/ui/CHudPause_patches.cpp @@ -117,11 +117,11 @@ PPC_FUNC(sub_824B0930) auto pHudPause = (SWA::CHudPause*)g_memory.Translate(ctx.r3.u32); auto pInputState = SWA::CInputState::GetInstance(); - g_achievementMenuIntroTime += g_deltaTime; + g_achievementMenuIntroTime += App::s_deltaTime; if (g_isAchievementMenuOutro) { - g_achievementMenuOutroTime += g_deltaTime; + g_achievementMenuOutroTime += App::s_deltaTime; // Re-open pause menu after achievement menu closes with delay. if (g_achievementMenuOutroTime >= g_achievementMenuOutroThreshold) diff --git a/UnleashedRecomp/patches/ui/CTitleStateIntro_patches.cpp b/UnleashedRecomp/patches/ui/CTitleStateIntro_patches.cpp index 07523e9..2022f80 100644 --- a/UnleashedRecomp/patches/ui/CTitleStateIntro_patches.cpp +++ b/UnleashedRecomp/patches/ui/CTitleStateIntro_patches.cpp @@ -3,6 +3,7 @@ #include #include #include +#include static bool g_quitMessageOpen = false; static bool g_quitMessageFaderBegun = false; @@ -23,7 +24,7 @@ static bool ProcessQuitMessage() switch (g_quitMessageResult) { case 0: - Fader::FadeOut(1, []() { ExitProcess(0); }); + Fader::FadeOut(1, []() { App::Exit(); }); g_quitMessageFaderBegun = true; break; diff --git a/UnleashedRecomp/patches/ui/CTitleStateMenu_patches.cpp b/UnleashedRecomp/patches/ui/CTitleStateMenu_patches.cpp index f2fd944..e7f1516 100644 --- a/UnleashedRecomp/patches/ui/CTitleStateMenu_patches.cpp +++ b/UnleashedRecomp/patches/ui/CTitleStateMenu_patches.cpp @@ -20,7 +20,7 @@ static bool ProcessInstallMessage() if (g_installMessageFaderBegun) return true; - auto& str = g_isMissingDLC + auto& str = App::s_isMissingDLC ? Localise("Installer_Message_TitleMissingDLC") : Localise("Installer_Message_Title"); @@ -31,8 +31,7 @@ static bool ProcessInstallMessage() switch (g_installMessageResult) { case 0: - // TODO: replace ExitProcess with restart method using --install-dlc argument. - Fader::FadeOut(1, []() { ExitProcess(0); }); + Fader::FadeOut(1, []() { App::Exit({ "--install-dlc" }); }); g_installMessageFaderBegun = true; break; diff --git a/UnleashedRecomp/ui/button_guide.cpp b/UnleashedRecomp/ui/button_guide.cpp index 30f7a1d..e7be8fc 100644 --- a/UnleashedRecomp/ui/button_guide.cpp +++ b/UnleashedRecomp/ui/button_guide.cpp @@ -63,7 +63,7 @@ std::tuple, GuestTexture*> GetButtonIcon(EButtonIcon std::tuple btn; GuestTexture* texture; - auto isPlayStation = g_isAppInit + auto isPlayStation = App::s_isInit ? Config::ControllerIcons == EControllerIcons::PlayStation : hid::detail::g_inputDevice == hid::detail::EInputDevice::PlayStation; diff --git a/UnleashedRecomp/ui/message_window.cpp b/UnleashedRecomp/ui/message_window.cpp index b8d47e6..d12bb7f 100644 --- a/UnleashedRecomp/ui/message_window.cpp +++ b/UnleashedRecomp/ui/message_window.cpp @@ -65,7 +65,7 @@ public: { case SDL_KEYDOWN: { - if (g_isAppInit) + if (App::s_isInit) break; switch (event->key.keysym.scancode) @@ -93,7 +93,7 @@ public: case SDL_MOUSEBUTTONDOWN: { - if (g_isAppInit) + if (App::s_isInit) break; g_isAccepted = true; @@ -273,8 +273,8 @@ void MessageWindow::Draw() auto textMarginX = Scale(37); auto textMarginY = Scale(45); - bool isController = g_isAppInit ? true : hid::detail::IsInputDeviceController(); - bool isKeyboard = g_isAppInit ? false : hid::detail::g_inputDevice == hid::detail::EInputDevice::Keyboard; + bool isController = App::s_isInit ? true : hid::detail::IsInputDeviceController(); + bool isKeyboard = App::s_isInit ? false : hid::detail::g_inputDevice == hid::detail::EInputDevice::Keyboard; if (DrawContainer(g_appearTime, centre, { textSize.x / 2 + textMarginX, textSize.y / 2 + textMarginY }, !g_isControlsVisible)) { diff --git a/UnleashedRecomp/ui/window.cpp b/UnleashedRecomp/ui/window.cpp index 68ebab6..6612160 100644 --- a/UnleashedRecomp/ui/window.cpp +++ b/UnleashedRecomp/ui/window.cpp @@ -2,6 +2,7 @@ #include "sdl_listener.h" #include #include +#include bool m_isFullscreenKeyReleased = true; bool m_isResizing = false; @@ -18,7 +19,7 @@ int Window_OnSDLEvent(void*, SDL_Event* event) { case SDL_QUIT: Config::Save(); - ExitProcess(0); + App::Exit(); break; case SDL_KEYDOWN: