UI+build: Isolate wxWidgets code from non-GUI code (#1633)

This commit is contained in:
SSimco 2025-07-15 05:28:41 +03:00 committed by GitHub
parent 5f3c2816ec
commit 67de63bed6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
199 changed files with 2414 additions and 2091 deletions

View file

@ -597,10 +597,6 @@ else ()
target_link_libraries(CemuCafe PRIVATE libusb::libusb)
endif ()
if (ENABLE_WXWIDGETS)
target_link_libraries(CemuCafe PRIVATE wx::base wx::core)
endif()
if(WIN32)
target_link_libraries(CemuCafe PRIVATE iphlpapi)
endif()

View file

@ -1,5 +1,5 @@
#include "Cafe/OS/common/OSCommon.h"
#include "gui/wxgui.h"
#include "WindowSystem.h"
#include "Cafe/OS/libs/gx2/GX2.h"
#include "Cafe/GameProfile/GameProfile.h"
#include "Cafe/HW/Espresso/Interpreter/PPCInterpreterInternal.h"
@ -65,9 +65,6 @@
// HW interfaces
#include "Cafe/HW/SI/si.h"
// dependency to be removed
#include "gui/guiWrapper.h"
#include <time.h>
#if BOOST_OS_LINUX
@ -172,7 +169,7 @@ void LoadMainExecutable()
applicationRPX = RPLLoader_LoadFromMemory(rpxData, rpxSize, (char*)_pathToExecutable.c_str());
if (!applicationRPX)
{
wxMessageBox(_("Failed to run this title because the executable is damaged"));
WindowSystem::ShowErrorDialog(_tr("Failed to run this title because the executable is damaged"));
cemuLog_createLogFile(false);
cemuLog_waitForFlush();
exit(0);
@ -357,7 +354,7 @@ uint32 LoadSharedData()
void cemu_initForGame()
{
gui_updateWindowTitles(false, true, 0.0);
WindowSystem::UpdateWindowTitles(false, true, 0.0);
// input manager apply game profile
InputManager::instance().apply_game_profile();
// log info for launched title
@ -855,7 +852,7 @@ namespace CafeSystem
PPCTimer_waitForInit();
// start system
sSystemRunning = true;
gui_notifyGameLoaded();
WindowSystem::NotifyGameLoaded();
std::thread t(_LaunchTitleThread);
t.detach();
}

View file

@ -1,7 +1,7 @@
#include <wx/msgdlg.h>
#include <mutex>
#include <gui/helpers/wxHelpers.h>
#include "Cemu/Logging/CemuLogging.h"
#include "WindowSystem.h"
#include "config/ActiveSettings.h"
#include "util/crypto/aes128.h"
#include "Common/FileStream.h"
@ -75,7 +75,7 @@ void KeyCache_Prepare()
}
else
{
wxMessageBox(_("Unable to create file keys.txt\nThis can happen if Cemu does not have write permission to its own directory, the disk is full or if anti-virus software is blocking Cemu."), _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
WindowSystem::ShowErrorDialog(_tr("Unable to create file keys.txt\nThis can happen if Cemu does not have write permission to its own directory, the disk is full or if anti-virus software is blocking Cemu."), _tr("Error"), WindowSystem::ErrorCategory::KEYS_TXT_CREATION);
}
mtxKeyCache.unlock();
return;
@ -108,8 +108,8 @@ void KeyCache_Prepare()
continue;
if( strishex(line) == false )
{
auto errorMsg = formatWxString(_("Error in keys.txt at line {}"), lineNumber);
wxMessageBox(errorMsg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
auto errorMsg = _tr("Error in keys.txt at line {}", lineNumber);
WindowSystem::ShowErrorDialog(errorMsg, WindowSystem::ErrorCategory::KEYS_TXT_CREATION);
continue;
}
if(line.size() == 32 )

View file

@ -85,7 +85,7 @@ bool GraphicPack2::LoadGraphicPack(const fs::path& rulesPath, IniParser& rules)
auto gp = std::make_shared<GraphicPack2>(rulesPath, rules);
// check if enabled and preset set
const auto& config_entries = g_config.data().graphic_pack_entries;
const auto& config_entries = GetConfigHandle().data().graphic_pack_entries;
// legacy absolute path checking for not breaking compatibility
auto file = gp->GetRulesPath();

View file

@ -1,13 +1,12 @@
#include "Cafe/GraphicPack/GraphicPack2.h"
#include "Cemu/Logging/CemuLogging.h"
#include "Common/FileStream.h"
#include "WindowSystem.h"
#include "util/helpers/StringParser.h"
#include "Cemu/PPCAssembler/ppcAssembler.h"
#include "Cafe/OS/RPL/rpl_structs.h"
#include "boost/algorithm/string.hpp"
#include "gui/wxgui.h" // for wxMessageBox
#include "gui/helpers/wxHelpers.h"
// error handler
void PatchErrorHandler::printError(class PatchGroup* patchGroup, sint32 lineNumber, std::string_view errorMsg)
{
@ -40,13 +39,13 @@ void PatchErrorHandler::printError(class PatchGroup* patchGroup, sint32 lineNumb
void PatchErrorHandler::showStageErrorMessageBox()
{
wxString errorMsg;
std::string errorMsg;
if (m_gp)
{
if (m_stage == STAGE::PARSER)
errorMsg.assign(formatWxString(_("Failed to load patches for graphic pack \'{}\'"), m_gp->GetName()));
errorMsg.assign(_tr("Failed to load patches for graphic pack \'{}\'", m_gp->GetName()));
else
errorMsg.assign(formatWxString(_("Failed to apply patches for graphic pack \'{}\'"), m_gp->GetName()));
errorMsg.assign(_tr("Failed to apply patches for graphic pack \'{}\'", m_gp->GetName()));
}
else
{
@ -55,7 +54,7 @@ void PatchErrorHandler::showStageErrorMessageBox()
if (cemuLog_isLoggingEnabled(LogType::Patches))
{
errorMsg.append("\n \n")
.append(_("Details:"))
.append(_tr("Details:"))
.append("\n");
for (auto& itr : errorMessages)
{
@ -64,7 +63,7 @@ void PatchErrorHandler::showStageErrorMessageBox()
}
}
wxMessageBox(errorMsg, _("Graphic pack error"));
WindowSystem::ShowErrorDialog(errorMsg, _tr("Graphic pack error"), WindowSystem::ErrorCategory::GRAPHIC_PACKS);
}
// loads Cemu-style patches (patch_<anything>.asm)

View file

@ -1,19 +1,20 @@
#include "gui/guiWrapper.h"
#include "Common/precompiled.h"
#include "Debugger.h"
#include "Cafe/OS/RPL/rpl_structs.h"
#include "Cemu/PPCAssembler/ppcAssembler.h"
#include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h"
#include "Cemu/ExpressionParser/ExpressionParser.h"
#include "gui/debugger/DebuggerWindow2.h"
#include "Cafe/OS/libs/coreinit/coreinit.h"
#include "OS/RPL/rpl.h"
#include "util/helpers/helpers.h"
#if BOOST_OS_WINDOWS
#include <Windows.h>
#endif
DebuggerDispatcher g_debuggerDispatcher;
debuggerState_t debuggerState{ };
DebuggerBreakpoint* debugger_getFirstBP(uint32 address)
@ -337,7 +338,7 @@ void debugger_toggleBreakpoint(uint32 address, bool state, DebuggerBreakpoint* b
{
bp->enabled = state;
debugger_updateExecutionBreakpoint(address);
debuggerWindow_updateViewThreadsafe2();
g_debuggerDispatcher.UpdateViewThreadsafe();
}
else if (bpItr->isMemBP())
{
@ -359,7 +360,7 @@ void debugger_toggleBreakpoint(uint32 address, bool state, DebuggerBreakpoint* b
debugger_updateMemoryBreakpoint(bpItr);
else
debugger_updateMemoryBreakpoint(nullptr);
debuggerWindow_updateViewThreadsafe2();
g_debuggerDispatcher.UpdateViewThreadsafe();
}
return;
}
@ -496,7 +497,7 @@ void debugger_stepInto(PPCInterpreter_t* hCPU, bool updateDebuggerWindow = true)
debugger_updateExecutionBreakpoint(initialIP);
debuggerState.debugSession.instructionPointer = hCPU->instructionPointer;
if(updateDebuggerWindow)
debuggerWindow_moveIP();
g_debuggerDispatcher.MoveIP();
ppcRecompilerEnabled = isRecEnabled;
}
@ -515,7 +516,7 @@ bool debugger_stepOver(PPCInterpreter_t* hCPU)
// nothing to skip, use step-into
debugger_stepInto(hCPU);
debugger_updateExecutionBreakpoint(initialIP);
debuggerWindow_moveIP();
g_debuggerDispatcher.MoveIP();
ppcRecompilerEnabled = isRecEnabled;
return false;
}
@ -523,7 +524,7 @@ bool debugger_stepOver(PPCInterpreter_t* hCPU)
debugger_createCodeBreakpoint(initialIP + 4, DEBUGGER_BP_T_ONE_SHOT);
// step over current instruction (to avoid breakpoint)
debugger_stepInto(hCPU);
debuggerWindow_moveIP();
g_debuggerDispatcher.MoveIP();
// restore breakpoints
debugger_updateExecutionBreakpoint(initialIP);
// run
@ -621,8 +622,8 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
DebuggerBreakpoint* singleshotBP = debugger_getFirstBP(debuggerState.debugSession.instructionPointer, DEBUGGER_BP_T_ONE_SHOT);
if (singleshotBP)
debugger_deleteBreakpoint(singleshotBP);
debuggerWindow_notifyDebugBreakpointHit2();
debuggerWindow_updateViewThreadsafe2();
g_debuggerDispatcher.NotifyDebugBreakpointHit();
g_debuggerDispatcher.UpdateViewThreadsafe();
// reset step control
debuggerState.debugSession.stepInto = false;
debuggerState.debugSession.stepOver = false;
@ -639,14 +640,14 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
break; // if true is returned, continue with execution
}
debugger_createPPCStateSnapshot(hCPU);
debuggerWindow_updateViewThreadsafe2();
g_debuggerDispatcher.UpdateViewThreadsafe();
debuggerState.debugSession.stepOver = false;
}
if (debuggerState.debugSession.stepInto)
{
debugger_stepInto(hCPU);
debugger_createPPCStateSnapshot(hCPU);
debuggerWindow_updateViewThreadsafe2();
g_debuggerDispatcher.UpdateViewThreadsafe();
debuggerState.debugSession.stepInto = false;
continue;
}
@ -663,8 +664,8 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
debuggerState.debugSession.isTrapped = false;
debuggerState.debugSession.hCPU = nullptr;
debuggerWindow_updateViewThreadsafe2();
debuggerWindow_notifyRun();
g_debuggerDispatcher.UpdateViewThreadsafe();
g_debuggerDispatcher.NotifyRun();
}
void debugger_shouldBreak(PPCInterpreter_t* hCPU)

View file

@ -15,6 +15,69 @@
#define DEBUGGER_BP_T_GDBSTUB_TW 0x7C010008
#define DEBUGGER_BP_T_DEBUGGER_TW 0x7C020008
class DebuggerCallbacks
{
public:
virtual void UpdateViewThreadsafe() {}
virtual void NotifyDebugBreakpointHit() {}
virtual void NotifyRun() {}
virtual void MoveIP() {}
virtual void NotifyModuleLoaded(void* module) {}
virtual void NotifyModuleUnloaded(void* module) {}
virtual ~DebuggerCallbacks() = default;
};
class DebuggerDispatcher
{
private:
static inline class DefaultDebuggerCallbacks : public DebuggerCallbacks
{
} s_defaultDebuggerCallbacks;
DebuggerCallbacks* m_callbacks = &s_defaultDebuggerCallbacks;
public:
void SetDebuggerCallbacks(DebuggerCallbacks* debuggerCallbacks)
{
cemu_assert_debug(m_callbacks == &s_defaultDebuggerCallbacks);
m_callbacks = debuggerCallbacks;
}
void ClearDebuggerCallbacks()
{
cemu_assert_debug(m_callbacks != &s_defaultDebuggerCallbacks);
m_callbacks = &s_defaultDebuggerCallbacks;
}
void UpdateViewThreadsafe()
{
m_callbacks->UpdateViewThreadsafe();
}
void NotifyDebugBreakpointHit()
{
m_callbacks->NotifyDebugBreakpointHit();
}
void NotifyRun()
{
m_callbacks->NotifyRun();
}
void MoveIP()
{
m_callbacks->MoveIP();
}
void NotifyModuleLoaded(void* module)
{
m_callbacks->NotifyModuleLoaded(module);
}
void NotifyModuleUnloaded(void* module)
{
m_callbacks->NotifyModuleUnloaded(module);
}
} extern g_debuggerDispatcher;
struct DebuggerBreakpoint
{

View file

@ -1,6 +1,6 @@
#include "Cafe/HW/Latte/Core/LatteOverlay.h"
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
#include "config/CemuConfig.h"
@ -519,17 +519,17 @@ void LatteOverlay_render(bool pad_view)
return;
sint32 w = 0, h = 0;
if (pad_view && gui_isPadWindowOpen())
gui_getPadWindowPhysSize(w, h);
if (pad_view && WindowSystem::IsPadWindowOpen())
WindowSystem::GetPadWindowPhysSize(w, h);
else
gui_getWindowPhysSize(w, h);
WindowSystem::GetWindowPhysSize(w, h);
if (w == 0 || h == 0)
return;
const Vector2f window_size{ (float)w,(float)h };
float fontDPIScale = !pad_view ? gui_getWindowDPIScale() : gui_getPadDPIScale();
float fontDPIScale = !pad_view ? WindowSystem::GetWindowDPIScale() : WindowSystem::GetPadDPIScale();
float overlayFontSize = 14.0f * (float)config.overlay.text_scale / 100.0f * fontDPIScale;

View file

@ -1,6 +1,6 @@
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "Cafe/HW/Latte/Core/LatteOverlay.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
performanceMonitor_t performanceMonitor{};
@ -106,12 +106,12 @@ void LattePerformanceMonitor_frameEnd()
if (isFirstUpdate)
{
LatteOverlay_updateStats(0.0, 0, 0);
gui_updateWindowTitles(false, false, 0.0);
WindowSystem::UpdateWindowTitles(false, false, 0.0);
}
else
{
LatteOverlay_updateStats(fps, drawCallCounter / elapsedFrames, fastDrawCallCounter / elapsedFrames);
gui_updateWindowTitles(false, false, fps);
WindowSystem::UpdateWindowTitles(false, false, fps);
}
}
}

View file

@ -11,7 +11,7 @@
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "Cafe/GraphicPack/GraphicPack2.h"
#include "config/ActiveSettings.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
#include "Cafe/OS/libs/erreula/erreula.h"
#include "input/InputManager.h"
#include "Cafe/OS/libs/swkbd/swkbd.h"
@ -838,10 +838,10 @@ sint32 _currentOutputImageHeight = 0;
void LatteRenderTarget_getScreenImageArea(sint32* x, sint32* y, sint32* width, sint32* height, sint32* fullWidth, sint32* fullHeight, bool padView)
{
int w, h;
if(padView && gui_isPadWindowOpen())
gui_getPadWindowPhysSize(w, h);
if(padView && WindowSystem::IsPadWindowOpen())
WindowSystem::GetPadWindowPhysSize(w, h);
else
gui_getWindowPhysSize(w, h);
WindowSystem::GetWindowPhysSize(w, h);
sint32 scaledOutputX;
sint32 scaledOutputY;
@ -999,8 +999,8 @@ void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uin
return {pressed && !toggle, pressed && toggle};
};
const bool tabPressed = gui_isKeyDown(PlatformKeyCodes::TAB);
const bool ctrlPressed = gui_isKeyDown(PlatformKeyCodes::LCONTROL);
const bool tabPressed = WindowSystem::IsKeyDown(WindowSystem::PlatformKeyCodes::TAB);
const bool ctrlPressed = WindowSystem::IsKeyDown(WindowSystem::PlatformKeyCodes::LCONTROL);
const auto [vpad0Active, vpad0Toggle] = getVPADScreenActive(0);
const auto [vpad1Active, vpad1Toggle] = getVPADScreenActive(1);

View file

@ -6,7 +6,7 @@
#include "Cafe/HW/Latte/Core/FetchShader.h"
#include "Cemu/FileCache/FileCache.h"
#include "Cafe/GameProfile/GameProfile.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
#include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h"
@ -24,7 +24,6 @@
#include "Cafe/HW/Latte/Common/ShaderSerializer.h"
#include "util/helpers/Serializer.h"
#include <wx/msgdlg.h>
#include <audio/IAudioAPI.h>
#include <util/bootSound/BootSoundReader.h>
#include <thread>
@ -69,8 +68,6 @@ void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId);
bool LatteShaderCache_updatePipelineLoadingProgress();
void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateFunc, bool isPipelines);
void LatteShaderCache_handleDeprecatedCacheFiles(fs::path pathGeneric, fs::path pathGenericPre1_25_0, fs::path pathGenericPre1_16_0);
struct
{
struct
@ -360,10 +357,7 @@ void LatteShaderCache_Load()
RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId);
// get cache file name
const auto pathGeneric = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_shaders.bin", cacheTitleId);
const auto pathGenericPre1_25_0 = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}.bin", cacheTitleId); // before 1.25.0
const auto pathGenericPre1_16_0 = ActiveSettings::GetCachePath("shaderCache/transferable/{:08x}.bin", CafeSystem::GetRPXHashBase()); // before 1.16.0
LatteShaderCache_handleDeprecatedCacheFiles(pathGeneric, pathGenericPre1_25_0, pathGenericPre1_16_0);
// calculate extraVersion for transferable and precompiled shader cache
uint32 transferableExtraVersion = SHADER_CACHE_GENERIC_EXTRA_VERSION;
s_shaderCacheGeneric = FileCache::Open(pathGeneric, false, transferableExtraVersion); // legacy extra version (1.25.0 - 1.25.1b)
@ -511,7 +505,7 @@ void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateF
continue;
int w, h;
gui_getWindowPhysSize(w, h);
WindowSystem::GetWindowPhysSize(w, h);
const Vector2f window_size{ (float)w,(float)h };
ImGui_GetFont(window_size.y / 32.0f); // = 24 by default
@ -900,30 +894,3 @@ void LatteShaderCache_Close()
if (g_renderer->GetType() == RendererAPI::Vulkan)
VulkanPipelineStableCache::GetInstance().Close();
}
#include <wx/msgdlg.h>
void LatteShaderCache_handleDeprecatedCacheFiles(fs::path pathGeneric, fs::path pathGenericPre1_25_0, fs::path pathGenericPre1_16_0)
{
std::error_code ec;
bool hasOldCacheFiles = fs::exists(pathGenericPre1_25_0, ec) || fs::exists(pathGenericPre1_16_0, ec);
bool hasNewCacheFiles = fs::exists(pathGeneric, ec);
if (hasOldCacheFiles && !hasNewCacheFiles)
{
// ask user if they want to delete or keep the old cache file
auto infoMsg = _("Cemu detected that the shader cache for this game is outdated.\nOnly shader caches generated with Cemu 1.25.0 or above are supported.\n\nWe recommend deleting the outdated cache file as it will no longer be used by Cemu.");
wxMessageDialog dialog(nullptr, infoMsg, _("Outdated shader cache"),
wxYES_NO | wxCENTRE | wxICON_EXCLAMATION);
dialog.SetYesNoLabels(_("Delete outdated cache file [recommended]"), _("Keep outdated cache file"));
const auto result = dialog.ShowModal();
if (result == wxID_YES)
{
fs::remove(pathGenericPre1_16_0, ec);
fs::remove(pathGenericPre1_25_0, ec);
}
}
}

View file

@ -6,7 +6,7 @@
#include "Cafe/HW/Latte/Core/LatteAsyncCommands.h"
#include "Cafe/GameProfile/GameProfile.h"
#include "Cafe/GraphicPack/GraphicPack2.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
#include "Cafe/HW/Latte/Core/LatteBufferCache.h"
@ -115,7 +115,7 @@ int Latte_ThreadEntry()
{
SetThreadName("LatteThread");
sint32 w,h;
gui_getWindowPhysSize(w,h);
WindowSystem::GetWindowPhysSize(w,h);
// renderer
g_renderer->Initialize();
@ -166,8 +166,7 @@ int Latte_ThreadEntry()
g_renderer->DrawEmptyFrame(true);
g_renderer->DrawEmptyFrame(false);
gui_hasScreenshotRequest(); // keep the screenshot request queue empty
g_renderer->CancelScreenshotRequest(); // keep the screenshot request queue empty
std::this_thread::sleep_for(std::chrono::milliseconds(1000/60));
}

View file

@ -1,5 +1,5 @@
#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
#include "Cafe/HW/Latte/Core/LatteRingBuffer.h"
#include "Cafe/HW/Latte/Core/LatteDraw.h"
@ -19,7 +19,38 @@
#include "Cafe/HW/Latte/ISA/RegDefines.h"
#include "Cafe/OS/libs/gx2/GX2.h"
#include "gui/canvas/OpenGLCanvas.h"
class DefaultOpenGLCanvasCallbacks : public OpenGLCanvasCallbacks
{
} g_defaultOpenGLCanvasCallbacks;
OpenGLCanvasCallbacks* g_openGLCanvasCallbacks = &g_defaultOpenGLCanvasCallbacks;
void SetOpenGLCanvasCallbacks(OpenGLCanvasCallbacks* callbacks)
{
cemu_assert_debug(g_openGLCanvasCallbacks == &g_defaultOpenGLCanvasCallbacks);
g_openGLCanvasCallbacks = callbacks;
}
void ClearOpenGLCanvasCallbacks()
{
cemu_assert_debug(g_openGLCanvasCallbacks != &g_defaultOpenGLCanvasCallbacks);
g_openGLCanvasCallbacks = &g_defaultOpenGLCanvasCallbacks;
}
bool GLCanvas_HasPadViewOpen()
{
return g_openGLCanvasCallbacks->HasPadViewOpen();
}
bool GLCanvas_MakeCurrent(bool padView)
{
return g_openGLCanvasCallbacks->MakeCurrent(padView);
}
void GLCanvas_SwapBuffers(bool swapTV, bool swapDRC)
{
g_openGLCanvasCallbacks->SwapBuffers(swapTV, swapDRC);
}
#define STRINGIFY2(X) #X
#define STRINGIFY(X) STRINGIFY2(X)
@ -479,8 +510,7 @@ void OpenGLRenderer::ClearColorbuffer(bool padView)
void OpenGLRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool padView)
{
const bool hasScreenshotRequest = gui_hasScreenshotRequest();
if(!hasScreenshotRequest && m_screenshot_state == ScreenshotState::None)
if(!m_screenshot_requested && m_screenshot_state == ScreenshotState::None)
return;
if (IsPadWindowActive())
@ -563,9 +593,9 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
{
int windowWidth, windowHeight;
if (padView)
gui_getPadWindowPhysSize(windowWidth, windowHeight);
WindowSystem::GetPadWindowPhysSize(windowWidth, windowHeight);
else
gui_getWindowPhysSize(windowWidth, windowHeight);
WindowSystem::GetWindowPhysSize(windowWidth, windowHeight);
g_renderer->renderTarget_setViewport(0, 0, windowWidth, windowHeight, 0.0f, 1.0f);
g_renderer->ClearColorbuffer(padView);
}

View file

@ -6,6 +6,28 @@
#define GPU_GL_MAX_NUM_ATTRIBUTE (16) // Wii U GPU supports more than 16 but not all desktop GPUs do. Have to keep this at 16 until we find a better solution
class OpenGLCanvasCallbacks
{
public:
virtual bool HasPadViewOpen() const
{
return false;
}
virtual bool MakeCurrent(bool padView)
{
return false;
}
virtual void SwapBuffers(bool swapTV, bool swapDRC) {}
virtual ~OpenGLCanvasCallbacks() = default;
};
void SetOpenGLCanvasCallbacks(OpenGLCanvasCallbacks* callbacks);
void ClearOpenGLCanvasCallbacks();
bool GLCanvas_HasPadViewOpen();
bool GLCanvas_MakeCurrent(bool padView);
void GLCanvas_SwapBuffers(bool swapTV, bool swapDRC);
class OpenGLRenderer : public Renderer
{
friend class OpenGLCanvas;

View file

@ -1,5 +1,5 @@
#include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
#include "config/CemuConfig.h"
#include "Cafe/HW/Latte/Core/LatteOverlay.h"
@ -10,11 +10,6 @@
#include "config/ActiveSettings.h"
#include <wx/image.h>
#include <wx/dataobj.h>
#include <wx/clipbrd.h>
#include <wx/log.h>
std::unique_ptr<Renderer> g_renderer;
bool Renderer::GetVRAMInfo(int& usageInMB, int& totalInMB) const
@ -69,10 +64,10 @@ void Renderer::Shutdown()
bool Renderer::ImguiBegin(bool mainWindow)
{
sint32 w = 0, h = 0;
if(mainWindow)
gui_getWindowPhysSize(w, h);
else if(gui_isPadWindowOpen())
gui_getPadWindowPhysSize(w, h);
if (mainWindow)
WindowSystem::GetWindowPhysSize(w, h);
else if (WindowSystem::IsPadWindowOpen())
WindowSystem::GetPadWindowPhysSize(w, h);
else
return false;
@ -82,9 +77,9 @@ bool Renderer::ImguiBegin(bool mainWindow)
// select the right context
ImGui::SetCurrentContext(mainWindow ? imguiTVContext : imguiPadContext);
const Vector2f window_size{ (float)w,(float)h };
const Vector2f window_size{(float)w, (float)h};
auto& io = ImGui::GetIO();
io.DisplaySize = { window_size.x, window_size.y }; // should be only updated in the renderer and only when needed
io.DisplaySize = {window_size.x, window_size.y}; // should be only updated in the renderer and only when needed
ImGui_PrecacheFonts();
return true;
@ -114,107 +109,29 @@ uint8 Renderer::RGBComponentToSRGB(uint8 cli)
return (uint8)(cs * 255.0f);
}
static std::optional<fs::path> GenerateScreenshotFilename(bool isDRC)
void Renderer::RequestScreenshot(ScreenshotSaveFunction onSaveScreenshot)
{
fs::path screendir = ActiveSettings::GetUserDataPath("screenshots");
// build screenshot name with format Screenshot_YYYY-MM-DD_HH-MM-SS[_GamePad].png
// if the file already exists add a suffix counter (_2.png, _3.png etc)
std::time_t time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
std::tm* tm = std::localtime(&time_t);
std::string screenshotFileName = fmt::format("Screenshot_{:04}-{:02}-{:02}_{:02}-{:02}-{:02}", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
if (isDRC)
screenshotFileName.append("_GamePad");
fs::path screenshotPath;
for(sint32 i=0; i<999; i++)
{
screenshotPath = screendir;
if (i == 0)
screenshotPath.append(fmt::format("{}.png", screenshotFileName));
else
screenshotPath.append(fmt::format("{}_{}.png", screenshotFileName, i + 1));
std::error_code ec;
bool exists = fs::exists(screenshotPath, ec);
if (!ec && !exists)
return screenshotPath;
}
return std::nullopt;
m_screenshot_requested = true;
m_on_save_screenshot = onSaveScreenshot;
}
std::mutex s_clipboardMutex;
static bool SaveScreenshotToClipboard(const wxImage &image)
void Renderer::CancelScreenshotRequest()
{
bool success = false;
s_clipboardMutex.lock();
if (wxTheClipboard->Open())
{
wxTheClipboard->SetData(new wxImageDataObject(image));
wxTheClipboard->Close();
success = true;
}
s_clipboardMutex.unlock();
return success;
m_screenshot_requested = false;
m_on_save_screenshot = {};
}
static bool SaveScreenshotToFile(const wxImage &image, bool mainWindow)
void Renderer::SaveScreenshot(const std::vector<uint8>& rgb_data, int width, int height, bool mainWindow)
{
auto path = GenerateScreenshotFilename(!mainWindow);
if (!path) return false;
std::error_code ec;
fs::create_directories(path->parent_path(), ec);
if (ec) return false;
// suspend wxWidgets logging for the lifetime this object, to prevent a message box if wxImage::SaveFile fails
wxLogNull _logNo;
return image.SaveFile(path->wstring());
}
static void ScreenshotThread(std::vector<uint8> data, bool save_screenshot, int width, int height, bool mainWindow)
{
#if BOOST_OS_WINDOWS
// on Windows wxWidgets uses OLE API for the clipboard
// to make this work we need to call OleInitialize() on the same thread
OleInitialize(nullptr);
#endif
wxImage image(width, height, data.data(), true);
if (mainWindow)
{
if(SaveScreenshotToClipboard(image))
{
if (!save_screenshot)
LatteOverlay_pushNotification("Screenshot saved to clipboard", 2500);
}
else
{
LatteOverlay_pushNotification("Failed to open clipboard", 2500);
}
}
if (save_screenshot)
{
if (SaveScreenshotToFile(image, mainWindow))
{
if (mainWindow)
LatteOverlay_pushNotification("Screenshot saved", 2500);
}
else
{
LatteOverlay_pushNotification("Failed to save screenshot to file", 2500);
}
}
}
void Renderer::SaveScreenshot(const std::vector<uint8>& rgb_data, int width, int height, bool mainWindow) const
{
const bool save_screenshot = GetConfig().save_screenshot;
std::thread(ScreenshotThread, rgb_data, save_screenshot, width, height, mainWindow).detach();
std::thread(
[=, screenshotRequested = std::exchange(m_screenshot_requested, false), onSaveScreenshot = std::exchange(m_on_save_screenshot, {})]() {
if (screenshotRequested && onSaveScreenshot)
{
auto notificationMessage = onSaveScreenshot(rgb_data, width, height, mainWindow);
if (notificationMessage.has_value())
LatteOverlay_pushNotification(notificationMessage.value(), 2500);
}
})
.detach();
}

View file

@ -65,6 +65,10 @@ public:
virtual void DrawEmptyFrame(bool mainWindow) = 0;
virtual void SwapBuffers(bool swapTV, bool swapDRC) = 0;
using ScreenshotSaveFunction = std::function<std::optional<std::string>(const std::vector<uint8>&, int, int, bool)>;
void RequestScreenshot(ScreenshotSaveFunction onSaveScreenshot);
void CancelScreenshotRequest();
virtual void HandleScreenshotRequest(LatteTextureView* texView, bool padView){}
virtual void DrawBackbufferQuad(LatteTextureView* texView, RendererOutputShader* shader, bool useLinearTexFilter,
@ -168,7 +172,10 @@ protected:
Pad,
};
ScreenshotState m_screenshot_state = ScreenshotState::None;
void SaveScreenshot(const std::vector<uint8>& rgb_data, int width, int height, bool mainWindow) const;
bool m_screenshot_requested = false;
ScreenshotSaveFunction m_on_save_screenshot;
void SaveScreenshot(const std::vector<uint8>& rgb_data, int width, int height, bool mainWindow);
ImFontAtlas* imguiFontAtlas{};

View file

@ -1,7 +1,7 @@
#include "SwapchainInfoVk.h"
#include "config/CemuConfig.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
#include "Cafe/HW/Latte/Core/Latte.h"
#include "Cafe/HW/Latte/Core/LatteTiming.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
@ -9,7 +9,7 @@
SwapchainInfoVk::SwapchainInfoVk(bool mainWindow, Vector2i size) : mainWindow(mainWindow), m_desiredExtent(size)
{
auto& windowHandleInfo = mainWindow ? gui_getWindowInfo().canvas_main : gui_getWindowInfo().canvas_pad;
auto& windowHandleInfo = mainWindow ? WindowSystem::GetWindowInfo().canvas_main : WindowSystem::GetWindowInfo().canvas_pad;
auto renderer = VulkanRenderer::GetInstance();
m_instance = renderer->GetVkInstance();
m_logicalDevice = renderer->GetLogicalDevice();

View file

@ -1,9 +1,9 @@
#include "gui/MainWindow.h"
#if BOOST_OS_WINDOWS
#include <Windows.h>
#include "WindowSystem.h"
typedef LONG NTSTATUS;
typedef UINT32 D3DKMT_HANDLE;
@ -53,7 +53,7 @@ public:
private:
bool HasMonitorChanged()
{
HWND hWnd = (HWND)g_mainFrame->GetRenderCanvasHWND();
HWND hWnd = (HWND)WindowSystem::GetWindowInfo().canvas_main.surface;
if (hWnd == 0)
return true;
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
@ -71,9 +71,7 @@ private:
HRESULT GetAdapterHandleFromHwnd(D3DKMT_HANDLE* phAdapter, UINT* pOutput)
{
if (!g_mainFrame)
return E_FAIL;
HWND hWnd = (HWND)g_mainFrame->GetRenderCanvasHWND();
HWND hWnd = (HWND)WindowSystem::GetWindowInfo().canvas_main.surface;
if (hWnd == 0)
return E_FAIL;

View file

@ -18,7 +18,7 @@
#include "config/ActiveSettings.h"
#include "config/CemuConfig.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
#include "imgui/imgui_extension.h"
#include "imgui/imgui_impl_vulkan.h"
@ -27,11 +27,9 @@
#include "Cafe/HW/Latte/Core/LatteTiming.h" // vsync control
#include <cstdint>
#include <glslang/Public/ShaderLang.h>
#include <wx/msgdlg.h>
#include <wx/intl.h> // for localization
#ifndef VK_API_VERSION_MAJOR
#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU)
#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU)
@ -113,11 +111,11 @@ std::vector<VulkanRenderer::DeviceInfo> VulkanRenderer::GetDevices()
#if BOOST_OS_WINDOWS
requiredExtensions.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#elif BOOST_OS_LINUX
auto backend = gui_getWindowInfo().window_main.backend;
if(backend == WindowHandleInfo::Backend::X11)
auto backend = WindowSystem::GetWindowInfo().window_main.backend;
if(backend == WindowSystem::WindowHandleInfo::Backend::X11)
requiredExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
#ifdef HAS_WAYLAND
else if (backend == WindowHandleInfo::Backend::WAYLAND)
else if (backend == WindowSystem::WindowHandleInfo::Backend::Wayland)
requiredExtensions.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
#endif
#elif BOOST_OS_MACOS
@ -156,7 +154,7 @@ std::vector<VulkanRenderer::DeviceInfo> VulkanRenderer::GetDevices()
throw std::runtime_error("Failed to find a GPU with Vulkan support.");
// create tmp surface to create a logical device
auto surface = CreateFramebufferSurface(instance, gui_getWindowInfo().window_main);
auto surface = CreateFramebufferSurface(instance, WindowSystem::GetWindowInfo().window_main);
std::vector<VkPhysicalDevice> devices(device_count);
vkEnumeratePhysicalDevices(instance, &device_count, devices.data());
for (const auto& device : devices)
@ -309,7 +307,7 @@ void VulkanRenderer::GetDeviceFeatures()
cemuLog_log(LogType::Force, "VK_EXT_pipeline_creation_cache_control not supported. Cannot use asynchronous shader and pipeline compilation");
// if async shader compilation is enabled show warning message
if (GetConfig().async_compile)
LatteOverlay_pushNotification(_("Async shader compile is enabled but not supported by the graphics driver\nCemu will use synchronous compilation which can cause additional stutter").utf8_string(), 10000);
LatteOverlay_pushNotification(_tr("Async shader compile is enabled but not supported by the graphics driver\nCemu will use synchronous compilation which can cause additional stutter"), 10000);
}
if (!m_featureControl.deviceExtensions.custom_border_color_without_format)
{
@ -402,7 +400,7 @@ VulkanRenderer::VulkanRenderer()
throw std::runtime_error("Failed to find a GPU with Vulkan support.");
// create tmp surface to create a logical device
auto surface = CreateFramebufferSurface(m_instance, gui_getWindowInfo().window_main);
auto surface = CreateFramebufferSurface(m_instance, WindowSystem::GetWindowInfo().window_main);
auto& config = GetConfig();
decltype(config.graphic_device_uuid) zero{};
@ -810,8 +808,7 @@ bool VulkanRenderer::IsPadWindowActive()
void VulkanRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool padView)
{
const bool hasScreenshotRequest = gui_hasScreenshotRequest();
if (!hasScreenshotRequest && m_screenshot_state == ScreenshotState::None)
if (!m_screenshot_requested && m_screenshot_state == ScreenshotState::None)
return;
if (IsSwapchainInfoValid(false))
@ -1311,11 +1308,11 @@ std::vector<const char*> VulkanRenderer::CheckInstanceExtensionSupport(FeatureCo
#if BOOST_OS_WINDOWS
requiredInstanceExtensions.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#elif BOOST_OS_LINUX
auto backend = gui_getWindowInfo().window_main.backend;
if(backend == WindowHandleInfo::Backend::X11)
auto backend = WindowSystem::GetWindowInfo().window_main.backend;
if(backend == WindowSystem::WindowHandleInfo::Backend::X11)
requiredInstanceExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
#if HAS_WAYLAND
else if (backend == WindowHandleInfo::Backend::WAYLAND)
else if (backend == WindowSystem::WindowHandleInfo::Backend::Wayland)
requiredInstanceExtensions.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
#endif
#elif BOOST_OS_MACOS
@ -1457,20 +1454,21 @@ VkSurfaceKHR VulkanRenderer::CreateWaylandSurface(VkInstance instance, wl_displa
#endif // HAS_WAYLAND
#endif // BOOST_OS_LINUX
VkSurfaceKHR VulkanRenderer::CreateFramebufferSurface(VkInstance instance, struct WindowHandleInfo& windowInfo)
VkSurfaceKHR VulkanRenderer::CreateFramebufferSurface(VkInstance instance, WindowSystem::WindowHandleInfo& windowInfo)
{
#if BOOST_OS_WINDOWS
return CreateWinSurface(instance, windowInfo.hwnd);
return CreateWinSurface(instance, static_cast<HWND>(windowInfo.surface));
#elif BOOST_OS_LINUX
if(windowInfo.backend == WindowHandleInfo::Backend::X11)
return CreateXlibSurface(instance, windowInfo.xlib_display, windowInfo.xlib_window);
if(windowInfo.backend == WindowSystem::WindowHandleInfo::Backend::X11)
return CreateXlibSurface(instance, static_cast<Display*>(windowInfo.display), reinterpret_cast<Window>(windowInfo.surface));
#ifdef HAS_WAYLAND
if(windowInfo.backend == WindowHandleInfo::Backend::WAYLAND)
return CreateWaylandSurface(instance, windowInfo.display, windowInfo.surface);
if(windowInfo.backend == WindowSystem::WindowHandleInfo::Backend::Wayland)
return CreateWaylandSurface(instance, static_cast<wl_display*>(windowInfo.display), static_cast<wl_surface*>(windowInfo.surface));
#endif
return {};
#elif BOOST_OS_MACOS
return CreateCocoaSurface(instance, windowInfo.handle);
return CreateCocoaSurface(instance, windowInfo.surface);
#endif
}
@ -2746,11 +2744,11 @@ void VulkanRenderer::RecreateSwapchain(bool mainWindow, bool skipCreate)
if (mainWindow)
{
ImGui_ImplVulkan_Shutdown();
gui_getWindowPhysSize(size.x, size.y);
WindowSystem::GetWindowPhysSize(size.x, size.y);
}
else
{
gui_getPadWindowPhysSize(size.x, size.y);
WindowSystem::GetPadWindowPhysSize(size.x, size.y);
}
chainInfo.swapchainImageIndex = -1;
@ -2780,9 +2778,9 @@ bool VulkanRenderer::UpdateSwapchainProperties(bool mainWindow)
int width, height;
if (mainWindow)
gui_getWindowPhysSize(width, height);
WindowSystem::GetWindowPhysSize(width, height);
else
gui_getPadWindowPhysSize(width, height);
WindowSystem::GetPadWindowPhysSize(width, height);
auto extent = chainInfo.getExtent();
if (width != extent.width || height != extent.height)
stateChanged = true;

View file

@ -120,6 +120,11 @@ public:
bool neverSkipAccurateBarrier{false};
};
namespace WindowSystem
{
struct WindowHandleInfo;
};
class VulkanRenderer : public Renderer
{
friend class LatteQueryObjectVk;
@ -204,7 +209,7 @@ public:
#endif
#endif
static VkSurfaceKHR CreateFramebufferSurface(VkInstance instance, struct WindowHandleInfo& windowInfo);
static VkSurfaceKHR CreateFramebufferSurface(VkInstance instance, struct WindowSystem::WindowHandleInfo& windowInfo);
void AppendOverlayDebugInfo() override;

View file

@ -1,7 +1,8 @@
#include "Cafe/HW/MMU/MMU.h"
#include "Cafe/GraphicPack/GraphicPack2.h"
#include "Cemu/Logging/CemuLogging.h"
#include "WindowSystem.h"
#include "util/MemMapper/MemMapper.h"
#include <wx/msgdlg.h>
#include "config/ActiveSettings.h"
uint8* memory_base = NULL; // base address of the reserved 4GB space
@ -90,8 +91,8 @@ void MMURange::mapMem()
cemu_assert_debug(!m_isMapped);
if (MemMapper::AllocateMemory(memory_base + baseAddress, size, MemMapper::PAGE_PERMISSION::P_RW, true) == nullptr)
{
std::string errorMsg = fmt::format("Unable to allocate {} memory", name);
wxMessageBox(errorMsg.c_str(), "Error", wxOK | wxCENTRE | wxICON_ERROR);
std::string errorMsg = _tr("Unable to allocate {} memory", name);
WindowSystem::ShowErrorDialog(errorMsg, _tr("Error"));
#if BOOST_OS_WINDOWS
ExitProcess(-1);
#else
@ -133,7 +134,7 @@ void memory_init()
{
debug_printf("memory_init(): Unable to reserve 4GB of memory\n");
debugBreakpoint();
wxMessageBox("Unable to reserve 4GB of memory\n", "Error", wxOK | wxCENTRE | wxICON_ERROR);
WindowSystem::ShowErrorDialog(_tr("Unable to reserve 4GB of memory"), _tr("Error"));
exit(-1);
}
for (auto& itr : g_mmuRanges)

View file

@ -2,7 +2,6 @@
#include "iosu_ioctl.h"
#include "Cafe/OS/libs/nn_common.h"
#include "gui/CemuApp.h"
#include <algorithm>
#include <mutex>

View file

@ -14,7 +14,7 @@
#include "util/crypto/crc32.h"
#include "config/ActiveSettings.h"
#include "Cafe/OS/libs/coreinit/coreinit_DynLoad.h"
#include "gui/guiWrapper.h"
#include "WindowSystem.h"
class PPCCodeHeap : public VHeap
{
@ -1795,7 +1795,7 @@ void RPLLoader_UnloadModule(RPLModule* rpl)
RPLLoader_decrementModuleDependencyRefs(rpl);
// save module config for this module in the debugger
debuggerWindow_notifyModuleUnloaded(rpl);
g_debuggerDispatcher.NotifyModuleUnloaded(rpl);
// release memory
rplLoaderHeap_codeArea2.free(rpl->regionMappingBase_text.GetPtr());
@ -1878,7 +1878,7 @@ void RPLLoader_Link()
RPLLoader_LoadDebugSymbols(rplModuleList[i]);
rplModuleList[i]->isLinked = true; // mark as linked
GraphicPack2::NotifyModuleLoaded(rplModuleList[i]);
debuggerWindow_notifyModuleLoaded(rplModuleList[i]);
g_debuggerDispatcher.NotifyModuleLoaded(rplModuleList[i]);
}
}

View file

@ -6,8 +6,6 @@
#include <imgui.h>
#include "imgui/imgui_extension.h"
#include <wx/msgdlg.h>
#include "Cafe/OS/libs/coreinit/coreinit_FS.h"
#include "Cafe/OS/libs/coreinit/coreinit_Time.h"
#include "Cafe/OS/libs/vpad/vpad.h"

View file

@ -1,5 +1,4 @@
#include "Cafe/OS/common/OSCommon.h"
#include "gui/wxgui.h"
#include "nn_save.h"
#include "Cafe/OS/libs/nn_acp/nn_acp.h"
@ -229,78 +228,6 @@ namespace save
return ConvertACPToSaveStatus(acp::ACPUnmountSaveDir());
}
void _CheckAndMoveLegacySaves()
{
const uint64 titleId = CafeSystem::GetForegroundTitleId();
fs::path targetPath, sourcePath;
try
{
bool copiedUser = false, copiedCommon = false;
const auto sourceSavePath = ActiveSettings::GetMlcPath("emulatorSave/{:08x}", CafeSystem::GetRPXHashBase());
sourcePath = sourceSavePath;
if (fs::exists(sourceSavePath) && is_directory(sourceSavePath))
{
targetPath = ActiveSettings::GetMlcPath("usr/save/{:08x}/{:08x}/user/{:08x}", GetTitleIdHigh(titleId), GetTitleIdLow(titleId), 0x80000001);
fs::create_directories(targetPath);
copy(sourceSavePath, targetPath, fs::copy_options::overwrite_existing | fs::copy_options::recursive);
copiedUser = true;
}
const auto sourceCommonPath = ActiveSettings::GetMlcPath("emulatorSave/{:08x}_255", CafeSystem::GetRPXHashBase());
sourcePath = sourceCommonPath;
if (fs::exists(sourceCommonPath) && is_directory(sourceCommonPath))
{
targetPath = ActiveSettings::GetMlcPath("usr/save/{:08x}/{:08x}/user/common", GetTitleIdHigh(titleId), GetTitleIdLow(titleId));
fs::create_directories(targetPath);
copy(sourceCommonPath, targetPath, fs::copy_options::overwrite_existing | fs::copy_options::recursive);
copiedCommon = true;
}
if (copiedUser)
fs::remove_all(sourceSavePath);
if (copiedCommon)
fs::remove_all(sourceCommonPath);
}
catch (const std::exception& ex)
{
#if BOOST_OS_WINDOWS
std::wstringstream errorMsg;
errorMsg << L"Couldn't move your save files!" << std::endl << std::endl;
errorMsg << L"Error: " << ex.what() << std::endl << std::endl;
errorMsg << L"From:" << std::endl << sourcePath << std::endl << std::endl << "To:" << std::endl << targetPath;
const DWORD lastError = GetLastError();
if (lastError != ERROR_SUCCESS)
{
LPTSTR lpMsgBuf = nullptr;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, lastError, 0, (LPTSTR)&lpMsgBuf, 0, nullptr);
if (lpMsgBuf)
{
errorMsg << std::endl << std::endl << L"Details: " << lpMsgBuf;
LocalFree(lpMsgBuf);
}
else
{
errorMsg << std::endl << std::endl << L"Error Code: 0x" << std::hex << lastError;
}
}
errorMsg << std::endl << std::endl << "Continuing will create a new save at the target location." << std::endl << "Do you want to continue?";
int result = wxMessageBox(errorMsg.str(), "Save Migration - Error", wxCENTRE | wxYES_NO | wxICON_ERROR);
if (result != wxYES)
{
exit(0);
return;
}
#endif
}
}
SAVEStatus SAVEInit()
{
@ -321,8 +248,6 @@ namespace save
SAVEMountSaveDir();
g_nn_save->initialized = true;
_CheckAndMoveLegacySaves();
uint32 high = GetTitleIdHigh(titleId) & (~0xC);
uint32 low = GetTitleIdLow(titleId);

View file

@ -1,10 +1,10 @@
#include "Cafe/OS/common/OSCommon.h"
#include "Cafe/HW/Espresso/PPCCallback.h"
#include "gui/wxgui.h"
#include "Cafe/OS/libs/padscore/padscore.h"
#include "Cafe/OS/libs/coreinit/coreinit_Time.h"
#include "Cafe/OS/libs/coreinit/coreinit_Alarm.h"
#include "Cafe/OS/libs/coreinit/coreinit_SystemInfo.h"
#include "WindowSystem.h"
#include "input/InputManager.h"
// KPAD
@ -470,7 +470,7 @@ sint32 _KPADRead(uint32 channel, KPADStatus_t* samplingBufs, uint32 length, bety
samplingBufs->wpadErr = WPAD_ERR_NONE;
samplingBufs->data_format = controller->get_data_format();
samplingBufs->devType = controller->get_device_type();
if(!g_inputConfigWindowHasFocus)
if(!WindowSystem::InputConfigWindowHasFocus())
{
const auto btn_repeat = padscore::g_padscore.controller_data[channel].btn_repeat;
controller->KPADRead(*samplingBufs, btn_repeat);

View file

@ -1,12 +1,12 @@
#include "Cafe/OS/common/OSCommon.h"
#include "Cafe/HW/Espresso/PPCCallback.h"
#include "gui/wxgui.h"
#include "Cafe/OS/libs/vpad/vpad.h"
#include "audio/IAudioAPI.h"
#include "Cafe/OS/libs/coreinit/coreinit_Time.h"
#include "config/ActiveSettings.h"
#include "Cafe/OS/libs/coreinit/coreinit_Alarm.h"
#include "input/InputManager.h"
#include "WindowSystem.h"
#ifdef PUBLIC_RELASE
#define vpadbreak()
@ -263,7 +263,7 @@ namespace vpad
PPCCore_switchToScheduler();
}
if (!g_inputConfigWindowHasFocus)
if (!WindowSystem::InputConfigWindowHasFocus())
{
if (channel <= 1 && vpadDelayEnabled)
{