A tool for deriving PKG packet encryption keys for ps4 written in c++
| 1 | // SPDX-FileCopyrightText: Copyright 2025 shadPKG |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | |
| 4 | // ╔═══════════════════════════════════════════════════════════════════════════╗ |
| 5 | // ║ ShadPKG GUI - Main Entry Point ║ |
| 6 | // ║ ║ |
| 7 | // ║ ImGui + GLFW + OpenGL3 Application ║ |
| 8 | // ║ ║ |
| 9 | // ║ Window Layout: ║ |
| 10 | // ║ ┌──────────────┬──────────────────────────────────────────────────────┐ ║ |
| 11 | // ║ │ │ │ ║ |
| 12 | // ║ │ NAV BAR │ MAIN VIEWPORT │ ║ |
| 13 | // ║ │ │ (Dynamic view content) │ ║ |
| 14 | // ║ │ [Extract] │ │ ║ |
| 15 | // ║ │ [Inspect] │ │ ║ |
| 16 | // ║ │ [RIF Tool] ├──────────────────────────────────────────────────────┤ ║ |
| 17 | // ║ │ [Settings] │ CONSOLE LOG │ ║ |
| 18 | // ║ │ │ [INFO] System initialized... │ ║ |
| 19 | // ║ └──────────────┴──────────────────────────────────────────────────────┘ ║ |
| 20 | // ║ ║ |
| 21 | // ╚═══════════════════════════════════════════════════════════════════════════╝ |
| 22 | |
| 23 | #include "common/assert.h" |
| 24 | #include <assert.h> |
| 25 | #ifndef IM_ASSERT |
| 26 | #define IM_ASSERT(_EXPR) ASSERT(_EXPR) |
| 27 | #endif |
| 28 | #include "imgui.h" |
| 29 | #include "imgui_impl_glfw.h" |
| 30 | #include "imgui_impl_opengl3.h" |
| 31 | |
| 32 | #if defined(__APPLE__) |
| 33 | #include <OpenGL/gl3.h> |
| 34 | #elif defined(_WIN32) |
| 35 | #define WIN32_LEAN_AND_MEAN |
| 36 | #include <GL/gl.h> |
| 37 | #include <windows.h> |
| 38 | #else |
| 39 | #include <GL/gl.h> |
| 40 | #endif |
| 41 | #include <GLFW/glfw3.h> |
| 42 | |
| 43 | #include <cstdio> |
| 44 | #include <cstdlib> |
| 45 | #include <filesystem> |
| 46 | #include <string> |
| 47 | #include <vector> |
| 48 | |
| 49 | // GUI Components |
| 50 | #include "include/ConsoleLog.h" |
| 51 | #include "include/GUIContext.h" |
| 52 | #include "include/GuiLogSink.h" |
| 53 | #include "include/NavBar.h" |
| 54 | #include "include/StyleManager.h" |
| 55 | |
| 56 | // Views |
| 57 | #include "include/views/DecompilerView.h" |
| 58 | #include "include/views/ExtractorView.h" |
| 59 | #include "include/views/InspectorView.h" |
| 60 | #include "include/views/RIFView.h" |
| 61 | #include "include/views/SettingsView.h" |
| 62 | #include "include/views/StructEditorView.h" |
| 63 | |
| 64 | // Logging |
| 65 | #include "common/logging/backend.h" |
| 66 | #include "common/logging/log.h" |
| 67 | |
| 68 | using namespace ShadPKG::GUI; |
| 69 | |
| 70 | // ╔═══════════════════════════════════════════════════════════════════════════╗ |
| 71 | // ║ Global State ║ |
| 72 | // ╚═══════════════════════════════════════════════════════════════════════════╝ |
| 73 | static GUIContext g_Context; |
| 74 | static NavBar g_NavBar; |
| 75 | static ConsoleLog g_ConsoleLog; |
| 76 | static ExtractorView g_ExtractorView; |
| 77 | static InspectorView g_InspectorView; |
| 78 | static RIFView g_RIFView; |
| 79 | static SettingsView g_SettingsView; |
| 80 | static DecompilerView g_DecompilerView; |
| 81 | |
| 82 | // Drag & drop file paths pending processing |
| 83 | static std::vector<std::string> g_DroppedFiles; |
| 84 | static bool g_HasDroppedFiles = false; |
| 85 | |
| 86 | // ┌─────────────────────────────────────────────────────────────────────────┐ |
| 87 | // │ GLFW Callbacks │ |
| 88 | // └─────────────────────────────────────────────────────────────────────────┘ |
| 89 | static void glfw_error_callback(int error, const char *description) { |
| 90 | fprintf(stderr, "GLFW Error %d: %s\n", error, description); |
| 91 | GuiLogSink::Instance().Error(std::string("GLFW Error: ") + description); |
| 92 | } |
| 93 | |
| 94 | static void glfw_drop_callback(GLFWwindow *window, int count, |
| 95 | const char **paths) { |
| 96 | g_DroppedFiles.clear(); |
| 97 | for (int i = 0; i < count; ++i) { |
| 98 | g_DroppedFiles.push_back(paths[i]); |
| 99 | } |
| 100 | g_HasDroppedFiles = true; |
| 101 | } |
| 102 | |
| 103 | // ┌─────────────────────────────────────────────────────────────────────────┐ |
| 104 | // │ Process Dropped Files │ |
| 105 | // └─────────────────────────────────────────────────────────────────────────┘ |
| 106 | static void ProcessDroppedFiles() { |
| 107 | if (!g_HasDroppedFiles) |
| 108 | return; |
| 109 | |
| 110 | for (const auto &path : g_DroppedFiles) { |
| 111 | // Forward to extractor view |
| 112 | g_ExtractorView.OnFileDrop(g_Context, path); |
| 113 | } |
| 114 | |
| 115 | g_DroppedFiles.clear(); |
| 116 | g_HasDroppedFiles = false; |
| 117 | } |
| 118 | |
| 119 | // ┌─────────────────────────────────────────────────────────────────────────┐ |
| 120 | // │ Draw Main Application Frame │ |
| 121 | // └─────────────────────────────────────────────────────────────────────────┘ |
| 122 | static void DrawMainFrame() { |
| 123 | // Get viewport |
| 124 | const ImGuiViewport *viewport = ImGui::GetMainViewport(); |
| 125 | |
| 126 | // Setup window flags for fullscreen window |
| 127 | ImGuiWindowFlags windowFlags = |
| 128 | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | |
| 129 | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | |
| 130 | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; |
| 131 | |
| 132 | // Cover entire viewport |
| 133 | ImGui::SetNextWindowPos(viewport->WorkPos); |
| 134 | ImGui::SetNextWindowSize(viewport->WorkSize); |
| 135 | ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); |
| 136 | ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); |
| 137 | ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); |
| 138 | |
| 139 | ImGui::Begin("##MainWindow", nullptr, windowFlags); |
| 140 | |
| 141 | ImGui::PopStyleVar(3); |
| 142 | |
| 143 | // ═══════════════════════════════════════════════════════════════════════ |
| 144 | // Layout: NavBar | ContentArea |
| 145 | // ═══════════════════════════════════════════════════════════════════════ |
| 146 | |
| 147 | // Draw NavBar on the left |
| 148 | g_NavBar.Draw(g_Context); |
| 149 | |
| 150 | ImGui::SameLine(); |
| 151 | |
| 152 | // Content area (view + console) |
| 153 | ImGui::BeginChild("##content_area", ImVec2(0, 0), false); |
| 154 | |
| 155 | float contentHeight = ImGui::GetContentRegionAvail().y; |
| 156 | float consoleHeight = g_ConsoleLog.IsExpanded() ? 180.0f : 30.0f; |
| 157 | if (consoleHeight > contentHeight) { |
| 158 | consoleHeight = contentHeight; |
| 159 | } |
| 160 | if (consoleHeight < 0.0f) { |
| 161 | consoleHeight = 0.0f; |
| 162 | } |
| 163 | float viewHeight = contentHeight - consoleHeight; |
| 164 | if (viewHeight < 0.0f) { |
| 165 | viewHeight = 0.0f; |
| 166 | } |
| 167 | |
| 168 | if (viewHeight > 1.0f) { |
| 169 | ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(16, 16)); |
| 170 | ImGui::BeginChild("##view_area", ImVec2(0, viewHeight), true); |
| 171 | |
| 172 | switch (g_Context.GetCurrentView()) { |
| 173 | case GUIContext::View::Extractor: |
| 174 | g_ExtractorView.Draw(g_Context); |
| 175 | break; |
| 176 | case GUIContext::View::Inspector: |
| 177 | g_InspectorView.Draw(g_Context); |
| 178 | break; |
| 179 | case GUIContext::View::RIF: |
| 180 | g_RIFView.Draw(g_Context); |
| 181 | break; |
| 182 | case GUIContext::View::Settings: |
| 183 | g_SettingsView.Draw(g_Context); |
| 184 | break; |
| 185 | // Static instance moved to file scope or initialized elsewhere if needed |
| 186 | // For now, rely on global or member instance (the include must be global) |
| 187 | // Actually, g_StructEditorView declaration should be kept here if it's |
| 188 | // local static, BUT the type definition from include must be global. |
| 189 | static StructEditorView g_StructEditorView; |
| 190 | |
| 191 | // ... |
| 192 | |
| 193 | case GUIContext::View::Decompiler: |
| 194 | g_DecompilerView.Draw(g_Context); |
| 195 | break; |
| 196 | case GUIContext::View::StructEditor: |
| 197 | g_StructEditorView.Draw(g_Context); |
| 198 | break; |
| 199 | } |
| 200 | |
| 201 | ImGui::EndChild(); |
| 202 | ImGui::PopStyleVar(); |
| 203 | } |
| 204 | |
| 205 | // ┌─────────────────────────────────────────────────────────────────────────┐ |
| 206 | // │ Console Log at bottom of content area │ |
| 207 | // └─────────────────────────────────────────────────────────────────────────┘ |
| 208 | if (consoleHeight > 1.0f) { |
| 209 | g_ConsoleLog.Draw(consoleHeight - 30.0f); |
| 210 | } |
| 211 | |
| 212 | ImGui::EndChild(); // Close ##content_area |
| 213 | |
| 214 | ImGui::End(); // MainWindow |
| 215 | } |
| 216 | |
| 217 | // ╔═══════════════════════════════════════════════════════════════════════════╗ |
| 218 | // ║ Main Entry Point ║ |
| 219 | // ╚═══════════════════════════════════════════════════════════════════════════╝ |
| 220 | int main(int argc, char *argv[]) { |
| 221 | // Initialize logging |
| 222 | Common::Log::Initialize("shadpkg_gui.log"); |
| 223 | Common::Log::SetColorConsoleBackendEnabled(true); |
| 224 | LOG_INFO(Common, "[GUI] Starting ShadPKG GUI"); |
| 225 | |
| 226 | // Setup GLFW |
| 227 | glfwSetErrorCallback(glfw_error_callback); |
| 228 | if (!glfwInit()) { |
| 229 | LOG_ERROR(Common, "[GUI] Failed to initialize GLFW"); |
| 230 | return 1; |
| 231 | } |
| 232 | |
| 233 | // GL context hints |
| 234 | #if defined(__APPLE__) |
| 235 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); |
| 236 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); |
| 237 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); |
| 238 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); |
| 239 | const char *glslVersion = "#version 150"; |
| 240 | #else |
| 241 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); |
| 242 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); |
| 243 | const char *glslVersion = "#version 130"; |
| 244 | #endif |
| 245 | |
| 246 | // Create window |
| 247 | GLFWwindow *window = glfwCreateWindow(1280, 800, "ShadPKG", nullptr, nullptr); |
| 248 | if (window == nullptr) { |
| 249 | LOG_ERROR(Common, "[GUI] Failed to create GLFW window"); |
| 250 | glfwTerminate(); |
| 251 | return 1; |
| 252 | } |
| 253 | |
| 254 | glfwMakeContextCurrent(window); |
| 255 | glfwSwapInterval(1); // Enable vsync |
| 256 | |
| 257 | // Setup drag & drop |
| 258 | glfwSetDropCallback(window, glfw_drop_callback); |
| 259 | |
| 260 | // Setup ImGui context |
| 261 | IMGUI_CHECKVERSION(); |
| 262 | ImGui::CreateContext(); |
| 263 | ImGuiIO &io = ImGui::GetIO(); |
| 264 | io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; |
| 265 | io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; |
| 266 | |
| 267 | // Apply custom style |
| 268 | SetupImGuiStyle(); |
| 269 | |
| 270 | std::filesystem::path executableDir; |
| 271 | if (argv != nullptr && argc > 0 && argv[0] != nullptr) { |
| 272 | std::error_code ec; |
| 273 | const auto absolutePath = std::filesystem::absolute(argv[0], ec); |
| 274 | if (!ec) { |
| 275 | executableDir = absolutePath.parent_path(); |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | LoadFonts(io, executableDir); |
| 280 | |
| 281 | // Setup Platform/Renderer backends |
| 282 | ImGui_ImplGlfw_InitForOpenGL(window, true); |
| 283 | ImGui_ImplOpenGL3_Init(glslVersion); |
| 284 | |
| 285 | // Window background color |
| 286 | ImVec4 clearColor = Colors::WindowBg; |
| 287 | |
| 288 | GuiLogSink::Instance().Info("ShadPKG GUI initialized"); |
| 289 | |
| 290 | // ═══════════════════════════════════════════════════════════════════════ |
| 291 | // Main Loop |
| 292 | // ═══════════════════════════════════════════════════════════════════════ |
| 293 | while (!glfwWindowShouldClose(window)) { |
| 294 | glfwPollEvents(); |
| 295 | |
| 296 | // Process any dropped files |
| 297 | ProcessDroppedFiles(); |
| 298 | |
| 299 | // Start ImGui frame |
| 300 | ImGui_ImplOpenGL3_NewFrame(); |
| 301 | ImGui_ImplGlfw_NewFrame(); |
| 302 | ImGui::NewFrame(); |
| 303 | |
| 304 | // Draw the application |
| 305 | DrawMainFrame(); |
| 306 | |
| 307 | // Render |
| 308 | ImGui::Render(); |
| 309 | int displayW, displayH; |
| 310 | glfwGetFramebufferSize(window, &displayW, &displayH); |
| 311 | glViewport(0, 0, displayW, displayH); |
| 312 | glClearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w); |
| 313 | glClear(GL_COLOR_BUFFER_BIT); |
| 314 | ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); |
| 315 | |
| 316 | glfwSwapBuffers(window); |
| 317 | } |
| 318 | |
| 319 | // Cleanup |
| 320 | ImGui_ImplOpenGL3_Shutdown(); |
| 321 | ImGui_ImplGlfw_Shutdown(); |
| 322 | ImGui::DestroyContext(); |
| 323 | |
| 324 | glfwDestroyWindow(window); |
| 325 | glfwTerminate(); |
| 326 | |
| 327 | LOG_INFO(Common, "[GUI] ShadPKG GUI shutdown"); |
| 328 | Common::Log::Stop(); |
| 329 | |
| 330 | return 0; |
| 331 | } |
| 332 |