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 | #pragma once |
| 5 | |
| 6 | #include <ctime> |
| 7 | #include <cstdio> |
| 8 | #include <mutex> |
| 9 | #include <string> |
| 10 | #include <vector> |
| 11 | |
| 12 | // ╔═══════════════════════════════════════════════════════════════════════════╗ |
| 13 | // ║ GuiLogSink: Thread-safe log backend for ImGui console display ║ |
| 14 | // ║ ║ |
| 15 | // ║ Captures LOG_INFO, LOG_WARNING, LOG_ERROR from Common::Log and stores ║ |
| 16 | // ║ them for real-time display in the ImGui console panel. ║ |
| 17 | // ╚═══════════════════════════════════════════════════════════════════════════╝ |
| 18 | |
| 19 | namespace ShadPKG::GUI { |
| 20 | |
| 21 | // ┌─────────────────────────────────────────────────────────────────────────┐ |
| 22 | // │ LogLevel: Severity levels for log entries │ |
| 23 | // │ │ |
| 24 | // │ INFO ─── General information (green) │ |
| 25 | // │ WARN ─── Warnings (yellow/orange) │ |
| 26 | // │ ERROR ─── Errors (red) │ |
| 27 | // └─────────────────────────────────────────────────────────────────────────┘ |
| 28 | enum class LogLevel { Info = 0, Warning = 1, Error = 2 }; |
| 29 | |
| 30 | struct LogEntry { |
| 31 | LogLevel level; |
| 32 | std::string message; |
| 33 | std::string timestamp; |
| 34 | std::string category; |
| 35 | }; |
| 36 | |
| 37 | // ┌─────────────────────────────────────────────────────────────────────────┐ |
| 38 | // │ GuiLogSink: Singleton log collector │ |
| 39 | // └─────────────────────────────────────────────────────────────────────────┘ |
| 40 | class GuiLogSink { |
| 41 | public: |
| 42 | static GuiLogSink &Instance() { |
| 43 | static GuiLogSink instance; |
| 44 | return instance; |
| 45 | } |
| 46 | |
| 47 | // Thread-safe log addition |
| 48 | void Add(LogLevel level, const std::string &category, |
| 49 | const std::string &msg) { |
| 50 | std::lock_guard<std::mutex> lock(logMutex_); |
| 51 | |
| 52 | LogEntry entry; |
| 53 | entry.level = level; |
| 54 | entry.message = msg; |
| 55 | entry.category = category; |
| 56 | entry.timestamp = GetTimeString(); |
| 57 | |
| 58 | logs_.push_back(entry); |
| 59 | |
| 60 | // Limit max entries to prevent memory issues |
| 61 | if (logs_.size() > maxEntries_) { |
| 62 | logs_.erase(logs_.begin()); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | // Convenience methods |
| 67 | void Info(const std::string &msg) { Add(LogLevel::Info, "GUI", msg); } |
| 68 | void Warn(const std::string &msg) { Add(LogLevel::Warning, "GUI", msg); } |
| 69 | void Error(const std::string &msg) { Add(LogLevel::Error, "GUI", msg); } |
| 70 | |
| 71 | // Get a copy of logs for rendering (thread-safe) |
| 72 | std::vector<LogEntry> GetLogs() const { |
| 73 | std::lock_guard<std::mutex> lock(logMutex_); |
| 74 | return logs_; |
| 75 | } |
| 76 | |
| 77 | void Clear() { |
| 78 | std::lock_guard<std::mutex> lock(logMutex_); |
| 79 | logs_.clear(); |
| 80 | } |
| 81 | |
| 82 | bool IsAutoScroll() const { return autoScroll_; } |
| 83 | void SetAutoScroll(bool enabled) { autoScroll_ = enabled; } |
| 84 | |
| 85 | size_t GetMaxEntries() const { return maxEntries_; } |
| 86 | void SetMaxEntries(size_t max) { maxEntries_ = max; } |
| 87 | |
| 88 | private: |
| 89 | GuiLogSink() = default; |
| 90 | |
| 91 | static std::string GetTimeString() { |
| 92 | time_t now = time(nullptr); |
| 93 | struct tm *t = localtime(&now); |
| 94 | char buffer[16]; |
| 95 | snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d", t->tm_hour, t->tm_min, |
| 96 | t->tm_sec); |
| 97 | return std::string(buffer); |
| 98 | } |
| 99 | |
| 100 | mutable std::mutex logMutex_; |
| 101 | std::vector<LogEntry> logs_; |
| 102 | bool autoScroll_ = true; |
| 103 | size_t maxEntries_ = 1000; |
| 104 | }; |
| 105 | |
| 106 | } // namespace ShadPKG::GUI |
| 107 |