Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ps2xRuntime/src/lib/Kernel/Syscalls/Helpers/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <cstddef>
#include <cstdint>
#include <thread>
#include <unordered_map>

inline std::unordered_map<int, FILE *> g_fileDescriptors;
inline int g_nextFd = 3; // Start after stdin, stdout, stderr
Expand Down
80 changes: 26 additions & 54 deletions ps2xStudio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -36,75 +29,38 @@ 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)

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
)

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")
Expand All @@ -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"
"$<TARGET_FILE_DIR:ps2xStudio>/external"
)
endif()

if(COMMAND ps2x_stage_ffmpeg_runtime_dlls)
Expand All @@ -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
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>:/SUBSYSTEM:WINDOWS>
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>:/ENTRY:mainCRTStartup>
)
elseif(MINGW)
target_link_options(ps2xStudio PRIVATE
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>:-mwindows>
)
endif()
endif()
endif()
25 changes: 25 additions & 0 deletions ps2xStudio/README.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion ps2xStudio/include/StudioState.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ enum class OverrideStatus {
};

enum class ThemeMode {
Dark, Light, Custom
Dark, Light, Custom, PS2
};

struct AppSettings {
Expand Down
47 changes: 45 additions & 2 deletions ps2xStudio/src/GUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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<int>(state.settings.theme);
if (ImGui::Combo("Theme Mode", &current, themes, 3)) {
if (ImGui::Combo("Theme Mode", &current, themes, 4)) {
state.settings.theme = static_cast<ThemeMode>(current);
StyleManager::ApplyTheme(state.settings.theme, state.settings);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -364,6 +406,7 @@ void GUI::DrawStudio(StudioState& state) {
}

DrawSettingsWindow(state);
DrawHelpWindow(state);

// ---- Explorer Panel ----
ImGui::Begin("Explorer");
Expand Down
Loading