From fa88b93c1f597436c00f729874d734c50fdd0337 Mon Sep 17 00:00:00 2001 From: Vova Vovchok Date: Sun, 12 Jul 2026 13:17:33 +0200 Subject: [PATCH] refactor: migrate ps2xStudio to Raylib/rlImGui, add help window, and include PS2 theme option --- .../src/lib/Kernel/Syscalls/Helpers/State.h | 2 + ps2xStudio/CMakeLists.txt | 80 ++++------- ps2xStudio/README.md | 25 ++++ ps2xStudio/include/StudioState.hpp | 2 +- ps2xStudio/src/GUI.cpp | 47 ++++++- ps2xStudio/src/main.cpp | 129 +++++------------- ps2xStudio/src/ui/StyleManager.cpp | 59 +++++++- 7 files changed, 194 insertions(+), 150 deletions(-) create mode 100644 ps2xStudio/README.md diff --git a/ps2xRuntime/src/lib/Kernel/Syscalls/Helpers/State.h b/ps2xRuntime/src/lib/Kernel/Syscalls/Helpers/State.h index c9551764b..becd4a479 100644 --- a/ps2xRuntime/src/lib/Kernel/Syscalls/Helpers/State.h +++ b/ps2xRuntime/src/lib/Kernel/Syscalls/Helpers/State.h @@ -2,6 +2,8 @@ #include #include +#include +#include inline std::unordered_map g_fileDescriptors; inline int g_nextFd = 3; // Start after stdin, stdout, stderr diff --git a/ps2xStudio/CMakeLists.txt b/ps2xStudio/CMakeLists.txt index 86cd9069c..962de61b6 100644 --- a/ps2xStudio/CMakeLists.txt +++ b/ps2xStudio/CMakeLists.txt @@ -8,13 +8,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) include(FetchContent) -FetchContent_Declare( - imgui - GIT_REPOSITORY https://github.com/ocornut/imgui.git - GIT_TAG docking - GIT_SHALLOW TRUE -) - FetchContent_Declare( imgui_colortextedit GIT_REPOSITORY https://github.com/BalazsJako/ImGuiColorTextEdit.git @@ -36,56 +29,20 @@ FetchContent_Declare( GIT_SHALLOW TRUE ) -set(SDL_TEST OFF CACHE BOOL "" FORCE) -set(SDL_TESTS OFF CACHE BOOL "" FORCE) -set(SDL_SHARED OFF CACHE BOOL "" FORCE) -set(SDL_STATIC ON CACHE BOOL "" FORCE) - -FetchContent_Declare( - SDL2 - GIT_REPOSITORY https://github.com/libsdl-org/SDL.git - GIT_TAG release-2.32.10 - GIT_SHALLOW TRUE -) - -set(SDL_SHARED ON CACHE BOOL "" FORCE) -set(SDL_STATIC OFF CACHE BOOL "" FORCE) - -FetchContent_MakeAvailable(imgui imgui_colortextedit imgui_club SDL2) +FetchContent_MakeAvailable(imgui_colortextedit imgui_club) FetchContent_GetProperties(imgui_file_dialog) if(NOT imgui_file_dialog_POPULATED) FetchContent_Populate(imgui_file_dialog) endif() -find_package(OpenGL REQUIRED) - -set(IMGUI_SOURCES - ${imgui_SOURCE_DIR}/imgui.cpp - ${imgui_SOURCE_DIR}/imgui_draw.cpp - ${imgui_SOURCE_DIR}/imgui_tables.cpp - ${imgui_SOURCE_DIR}/imgui_widgets.cpp - ${imgui_SOURCE_DIR}/imgui_demo.cpp - ${imgui_SOURCE_DIR}/backends/imgui_impl_sdl2.cpp - ${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp -) - -add_library(imgui_lib STATIC ${IMGUI_SOURCES}) - -target_include_directories(imgui_lib PUBLIC - ${imgui_SOURCE_DIR} - ${imgui_SOURCE_DIR}/backends -) - -target_link_libraries(imgui_lib PUBLIC SDL2::SDL2 OpenGL::GL) - add_library(imgui_colortextedit_lib STATIC ${imgui_colortextedit_SOURCE_DIR}/TextEditor.cpp ) target_include_directories(imgui_colortextedit_lib PUBLIC ${imgui_colortextedit_SOURCE_DIR}) -target_link_libraries(imgui_colortextedit_lib PUBLIC imgui_lib) +target_link_libraries(imgui_colortextedit_lib PUBLIC imgui) add_library(imgui_memory_editor_lib INTERFACE) @@ -93,7 +50,7 @@ target_include_directories(imgui_memory_editor_lib INTERFACE ${imgui_club_SOURCE_DIR}/imgui_memory_editor ) -target_link_libraries(imgui_memory_editor_lib INTERFACE imgui_lib) +target_link_libraries(imgui_memory_editor_lib INTERFACE imgui) add_library(imgui_filedialog_lib STATIC ${imgui_file_dialog_SOURCE_DIR}/ImGuiFileDialog.cpp @@ -101,10 +58,9 @@ add_library(imgui_filedialog_lib STATIC target_include_directories(imgui_filedialog_lib PUBLIC ${imgui_file_dialog_SOURCE_DIR} - ${imgui_SOURCE_DIR} ) -target_link_libraries(imgui_filedialog_lib PUBLIC imgui_lib) +target_link_libraries(imgui_filedialog_lib PUBLIC imgui) file(GLOB_RECURSE STUDIO_SOURCES "src/*.cpp") file(GLOB_RECURSE STUDIO_HEADERS "include/*.hpp") @@ -123,19 +79,23 @@ target_include_directories(ps2xStudio PRIVATE ) target_link_libraries(ps2xStudio PRIVATE - imgui_lib imgui_colortextedit_lib imgui_memory_editor_lib imgui_filedialog_lib ps2_recomp_lib ps2_analyzer_lib ps2_test_lib - SDL2::SDL2 - OpenGL::GL + raylib + rlImGui + imgui ) -if(WIN32) - target_link_libraries(ps2xStudio PRIVATE SDL2::SDL2main) +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/external") + add_custom_command(TARGET ps2xStudio POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/external" + "$/external" + ) endif() if(COMMAND ps2x_stage_ffmpeg_runtime_dlls) @@ -145,8 +105,20 @@ endif() include("${CMAKE_SOURCE_DIR}/ps2xRuntime/cmake/ReleaseMode.cmake") if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - EnableFastReleaseMode(imgui_lib) EnableFastReleaseMode(imgui_colortextedit_lib) EnableFastReleaseMode(imgui_filedialog_lib) EnableFastReleaseMode(ps2xStudio) + + if(WIN32 AND NOT PS2X_SHOW_WINDOWS_CONSOLE) + if(MSVC) + target_link_options(ps2xStudio PRIVATE + $<$,$>:/SUBSYSTEM:WINDOWS> + $<$,$>:/ENTRY:mainCRTStartup> + ) + elseif(MINGW) + target_link_options(ps2xStudio PRIVATE + $<$,$>:-mwindows> + ) + endif() + endif() endif() diff --git a/ps2xStudio/README.md b/ps2xStudio/README.md new file mode 100644 index 000000000..3da26f083 --- /dev/null +++ b/ps2xStudio/README.md @@ -0,0 +1,25 @@ +# PS2Recomp Studio (ps2xStudio) + +**ps2xStudio** is the graphical front-end application for the PS2Recomp toolset, providing an intuitive workflow for analyzing, reviewing, and recompiling PlayStation 2 (PS2) ELF executables into native C++ code. + +## Key Features + +- **ELF Analysis:** Automatically parses and decodes PS2 binary files to identify code sections and functions. +- **Visual Inspection:** Review assembly instructions, view hex data, and inspect the structural breakdown of the binary. +- **Function Overrides:** Manually mark functions to be skipped, stubbed, or forcefully recompiled, overriding the automatic heuristics. +- **Ghidra Integration:** Import function names and symbol data generated by Ghidra analysis via CSV files. +- **Recompilation Engine:** Connects directly to the `ps2xRecomp` backend to emit ready-to-compile C++ source code. +- **Configuration Management:** Dynamically edits and saves the `config.toml` file to persist your recompilation rules. + +## How to Use + +1. **Load a Binary**: Go to `File -> Open ELF...` and select your target PlayStation 2 executable (`.elf`). +2. **Run Analysis**: Start the initial binary sweep by pressing `F5` or clicking `Tools -> Analyze`. The Explorer panel will populate with the discovered functions. +3. **Import Symbols (Optional)**: If you have analyzed the binary in Ghidra and exported a CSV symbol map, load it via `File -> Import Ghidra CSV...`. This maps real function names to their addresses in the Explorer. +4. **Review & Configure**: Click on functions in the Explorer. In the Inspector panel, you can set the strategy (Default, Skip, Stub, Force Recompile). +5. **Set Output**: Specify where the generated C++ files should be saved (`File -> Set Output Directory...`). +6. **Recompile**: Start the C++ code generation by pressing `F7` or clicking `Tools -> Recompile`. + +## Settings & Themes + +You can customize the appearance of the Studio under `Settings -> Open Settings Window`. Here you can choose between Light, Dark, PS2, and Custom themes, adjust font scaling, and configure the default application window size. diff --git a/ps2xStudio/include/StudioState.hpp b/ps2xStudio/include/StudioState.hpp index dcfa44444..6f3b259b7 100644 --- a/ps2xStudio/include/StudioState.hpp +++ b/ps2xStudio/include/StudioState.hpp @@ -26,7 +26,7 @@ enum class OverrideStatus { }; enum class ThemeMode { - Dark, Light, Custom + Dark, Light, Custom, PS2 }; struct AppSettings { diff --git a/ps2xStudio/src/GUI.cpp b/ps2xStudio/src/GUI.cpp index 2132022c0..5d92788f5 100644 --- a/ps2xStudio/src/GUI.cpp +++ b/ps2xStudio/src/GUI.cpp @@ -17,6 +17,7 @@ static TextEditor ghidra_editor; static TextEditor log_editor; // TextEditor for logs - supports text selection static bool editors_initialized = false; static bool show_settings_window = false; +static bool show_help_window = false; static bool config_editor_needs_sync = false; static size_t last_log_version = 0; static bool s_wantsQuit = false; @@ -70,6 +71,40 @@ bool GUI::WantsQuit() { return s_wantsQuit; } +// ---- Help Window ---- +static void DrawHelpWindow(StudioState& state) { + if (!show_help_window) return; + + ImGui::SetNextWindowSize(ImVec2(600, 350), ImGuiCond_FirstUseEver); + if (ImGui::Begin("Help / About", &show_help_window)) { + if (ImGui::GetIO().Fonts->Fonts.Size > 0) { + ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]); + ImGui::TextColored(ImVec4(0.0f, 0.6f, 1.0f, 1.0f), "PS2Recomp Studio"); + ImGui::PopFont(); + } else { + ImGui::TextColored(ImVec4(0.0f, 0.6f, 1.0f, 1.0f), "PS2Recomp Studio"); + } + ImGui::Separator(); + ImGui::Spacing(); + ImGui::TextWrapped("This application is a graphical interface for analyzing and recompiling PlayStation 2 (PS2) ELF executables."); + ImGui::Spacing(); + ImGui::TextWrapped("How to use:"); + ImGui::BulletText("Load an ELF file (File -> Open ELF...)"); + ImGui::BulletText("Run Analysis (Tools -> Analyze or F5) to decode the binary"); + ImGui::BulletText("Optionally import a Ghidra CSV (File -> Import Ghidra CSV...) to name functions"); + ImGui::BulletText("Review functions in the Explorer and set overrides (e.g. Stub, Skip, Force Recompile)"); + ImGui::BulletText("Set an output directory (File -> Set Output Directory...)"); + ImGui::BulletText("Run Recompilation (Tools -> Recompile or F7) to generate C++ code"); + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Spacing(); + if (ImGui::Button("Close", ImVec2(120, 0))) { + show_help_window = false; + } + } + ImGui::End(); +} + // ---- Settings Window ---- static void DrawSettingsWindow(StudioState& state) { if (!show_settings_window) return; @@ -78,9 +113,9 @@ static void DrawSettingsWindow(StudioState& state) { if (ImGui::Begin("Settings", &show_settings_window)) { if (ImGui::CollapsingHeader("Theme", ImGuiTreeNodeFlags_DefaultOpen)) { - const char* themes[] = { "Dark", "Light", "Custom" }; + const char* themes[] = { "Dark", "Light", "Custom", "PS2" }; int current = static_cast(state.settings.theme); - if (ImGui::Combo("Theme Mode", ¤t, themes, 3)) { + if (ImGui::Combo("Theme Mode", ¤t, themes, 4)) { state.settings.theme = static_cast(current); StyleManager::ApplyTheme(state.settings.theme, state.settings); } @@ -328,6 +363,13 @@ void GUI::DrawStudio(StudioState& state) { ImGui::EndMenu(); } + if (ImGui::BeginMenu("Help")) { + if (ImGui::MenuItem("About / How to use")) { + show_help_window = true; + } + ImGui::EndMenu(); + } + // Show output path in menu bar std::string pathDisplay = state.GetEffectiveOutputPath(); float pathWidth = ImGui::CalcTextSize(pathDisplay.c_str()).x; @@ -364,6 +406,7 @@ void GUI::DrawStudio(StudioState& state) { } DrawSettingsWindow(state); + DrawHelpWindow(state); // ---- Explorer Panel ---- ImGui::Begin("Explorer"); diff --git a/ps2xStudio/src/main.cpp b/ps2xStudio/src/main.cpp index ee9b6ff71..9f82a79c5 100644 --- a/ps2xStudio/src/main.cpp +++ b/ps2xStudio/src/main.cpp @@ -1,29 +1,15 @@ #include "imgui.h" -#include "imgui_impl_sdl2.h" -#include "imgui_impl_opengl3.h" -#include -#include +#include "raylib.h" +#include "rlImGui.h" #include "GUI.hpp" #include "StudioState.hpp" +#include +#include int main(int argc, char** argv) { - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) return -1; + int screenWidth = 1280; + int screenHeight = 720; - SDL_DisplayMode displayMode; - SDL_GetCurrentDisplayMode(0, &displayMode); - - int screenWidth = displayMode.w; - int screenHeight = displayMode.h; - - int windowWidth = (int)(screenWidth * 0.8f); - int windowHeight = (int)(screenHeight * 0.8f); - - SDL_WindowFlags window_flags = (SDL_WindowFlags)( - SDL_WINDOW_OPENGL | - SDL_WINDOW_RESIZABLE - ); - - // Pre-load window settings before StudioState construction AppSettings tempSettings; try { std::ifstream file("studio_settings.ini"); @@ -47,113 +33,72 @@ int main(int argc, char** argv) { } } catch(...) {} - if (tempSettings.maximized) { - window_flags = (SDL_WindowFlags)(window_flags | SDL_WINDOW_MAXIMIZED); - } else { - windowWidth = tempSettings.windowWidth; - windowHeight = tempSettings.windowHeight; + if (!tempSettings.maximized && tempSettings.windowWidth > 0 && tempSettings.windowHeight > 0) { + screenWidth = tempSettings.windowWidth; + screenHeight = tempSettings.windowHeight; } - SDL_Window* window = SDL_CreateWindow( - "PS2Recomp Studio", - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - windowWidth, - windowHeight, - window_flags - ); - - if (!window) { - SDL_Quit(); - return -1; + SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI); + if (tempSettings.maximized) { + SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_MAXIMIZED); } - SDL_GLContext gl_context = SDL_GL_CreateContext(window); - SDL_GL_MakeCurrent(window, gl_context); - SDL_GL_SetSwapInterval(1); + InitWindow(screenWidth, screenHeight, "PS2Recomp Studio"); + SetTargetFPS(60); + + rlImGuiSetup(true); - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - // Create StudioState AFTER ImGui context StudioState state; - - // Initial font and theme setup GUI::ApplySettings(state); - - ImGui_ImplSDL2_InitForOpenGL(window, gl_context); - ImGui_ImplOpenGL3_Init("#version 130"); + ImGui::GetIO().Fonts->Build(); if (argc > 1) { state.StartAnalysis(argv[1]); } - bool done = false; - while (!done) { - SDL_Event event; - while (SDL_PollEvent(&event)) { - ImGui_ImplSDL2_ProcessEvent(&event); - if (event.type == SDL_QUIT) { - done = true; - } - if (event.type == SDL_WINDOWEVENT) { - if (event.window.event == SDL_WINDOWEVENT_RESIZED) { - state.settings.windowWidth = event.window.data1; - state.settings.windowHeight = event.window.data2; - } - if (event.window.event == SDL_WINDOWEVENT_MAXIMIZED) { - state.settings.maximized = true; - } - if (event.window.event == SDL_WINDOWEVENT_RESTORED) { - state.settings.maximized = false; - } - } + while (!WindowShouldClose()) { + if (IsWindowResized()) { + state.settings.windowWidth = GetScreenWidth(); + state.settings.windowHeight = GetScreenHeight(); + } + + if (IsWindowMaximized()) { + state.settings.maximized = true; + } else if (!IsWindowMaximized() && state.settings.maximized) { + state.settings.maximized = false; } - // Check GUI quit request (File > Exit) if (GUI::WantsQuit()) { - done = true; + break; } - // CRITICAL: Handle deferred font rebuild BEFORE NewFrame - // This is the safe place to modify fonts - outside of the rendering frame if (state.pendingFontRebuild.load()) { - // Rebuild fonts (clears atlas, adds fonts with new size) GUI::RebuildFontsIfNeeded(state); - // Build the font atlas; the OpenGL3 backend will detect the - // change and upload the new texture automatically on NewFrame. - io.Fonts->Build(); + ImGui::GetIO().Fonts->Build(); } - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplSDL2_NewFrame(); - ImGui::NewFrame(); + BeginDrawing(); + ClearBackground(Color{25, 25, 25, 255}); + rlImGuiBegin(); + GUI::DrawStudio(state); - ImGui::Render(); - glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - SDL_GL_SwapWindow(window); + rlImGuiEnd(); + EndDrawing(); } - // Save settings before shutdown state.SaveSettings(); if (state.workerThread.valid()) { state.workerThread.wait(); } - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplSDL2_Shutdown(); - ImGui::DestroyContext(); - SDL_GL_DeleteContext(gl_context); - SDL_DestroyWindow(window); - SDL_Quit(); + rlImGuiShutdown(); + CloseWindow(); return 0; } diff --git a/ps2xStudio/src/ui/StyleManager.cpp b/ps2xStudio/src/ui/StyleManager.cpp index d167ed434..b7b5aa5c6 100644 --- a/ps2xStudio/src/ui/StyleManager.cpp +++ b/ps2xStudio/src/ui/StyleManager.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "rlImGui.h" namespace StyleManager { @@ -37,7 +38,9 @@ void SetupFonts(AppSettings& settings) { loadedFont = io.Fonts->AddFontDefault(&config); } - // Font atlas will be built automatically by the backend + // Re-initialize rlImGui fonts (adds FontAwesome) and rebuild + rlImGuiEndInitImGui(); + io.Fonts->Build(); } void ApplyDarkTheme() { @@ -142,6 +145,57 @@ void ApplyLightTheme() { colors[ImGuiCol_NavHighlight] = accentMain; } +void ApplyPS2Theme() { + if (ImGui::GetCurrentContext() == nullptr) return; + + ImGuiStyle& style = ImGui::GetStyle(); + ImVec4* colors = style.Colors; + + const ImVec4 bgBase = ImVec4(0.00f, 0.00f, 0.05f, 1.00f); + const ImVec4 bgPanel = ImVec4(0.02f, 0.02f, 0.10f, 1.00f); + const ImVec4 bgInput = ImVec4(0.04f, 0.04f, 0.15f, 1.00f); + const ImVec4 accentMain = ImVec4(0.10f, 0.50f, 1.00f, 1.00f); + const ImVec4 accentHover = ImVec4(0.30f, 0.70f, 1.00f, 1.00f); + const ImVec4 accentActive = ImVec4(0.05f, 0.35f, 0.85f, 1.00f); + const ImVec4 textBright = ImVec4(0.90f, 0.95f, 1.00f, 1.00f); + const ImVec4 textDim = ImVec4(0.50f, 0.60f, 0.80f, 1.00f); + + colors[ImGuiCol_Text] = textBright; + colors[ImGuiCol_TextDisabled] = textDim; + colors[ImGuiCol_WindowBg] = bgBase; + colors[ImGuiCol_ChildBg] = bgPanel; + colors[ImGuiCol_PopupBg] = ImVec4(0.00f, 0.00f, 0.08f, 0.95f); + colors[ImGuiCol_Border] = ImVec4(0.20f, 0.30f, 0.60f, 0.50f); + colors[ImGuiCol_TitleBg] = ImVec4(0.00f, 0.00f, 0.08f, 1.00f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.05f, 0.10f, 0.25f, 1.00f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.00f, 0.00f, 0.08f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = bgBase; + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.10f, 0.20f, 0.40f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.20f, 0.35f, 0.60f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.30f, 0.50f, 0.80f, 1.00f); + colors[ImGuiCol_CheckMark] = accentMain; + colors[ImGuiCol_SliderGrab] = accentMain; + colors[ImGuiCol_SliderGrabActive] = accentActive; + colors[ImGuiCol_Button] = ImVec4(0.05f, 0.15f, 0.35f, 1.00f); + colors[ImGuiCol_ButtonHovered] = accentHover; + colors[ImGuiCol_ButtonActive] = accentActive; + colors[ImGuiCol_Header] = ImVec4(0.05f, 0.15f, 0.35f, 1.00f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.15f, 0.30f, 0.60f, 1.00f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.25f, 0.45f, 0.80f, 1.00f); + colors[ImGuiCol_FrameBg] = bgInput; + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.10f, 0.20f, 0.40f, 1.00f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.15f, 0.30f, 0.50f, 1.00f); + colors[ImGuiCol_Tab] = ImVec4(0.02f, 0.02f, 0.10f, 1.00f); + colors[ImGuiCol_TabHovered] = ImVec4(0.10f, 0.25f, 0.50f, 1.00f); + colors[ImGuiCol_TabActive] = ImVec4(0.05f, 0.15f, 0.35f, 1.00f); + colors[ImGuiCol_TabUnfocused] = ImVec4(0.00f, 0.00f, 0.05f, 1.00f); + colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.02f, 0.02f, 0.10f, 1.00f); + colors[ImGuiCol_DockingPreview] = accentMain; + colors[ImGuiCol_DockingEmptyBg] = bgBase; + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.10f, 0.50f, 1.00f, 0.50f); + colors[ImGuiCol_NavHighlight] = accentMain; +} + void ApplyCustomTheme(AppSettings& settings) { if (ImGui::GetCurrentContext() == nullptr) return; @@ -194,6 +248,9 @@ void ApplyTheme(ThemeMode mode, AppSettings& settings) { case ThemeMode::Light: ApplyLightTheme(); break; + case ThemeMode::PS2: + ApplyPS2Theme(); + break; case ThemeMode::Custom: ApplyDarkTheme(); ApplyCustomTheme(settings);