Seregon/ShadPKG

A tool for deriving PKG packet encryption keys for ps4 written in c++

C++/47.3 KB/No license
core/file_format/psf.h
1// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <chrono>
7#include <filesystem>
8#include <span>
9#include <string>
10#include <string_view>
11#include <unordered_map>
12#include <vector>
13#include <optional>
14#include "common/shadpkg_endian.h"
15
16constexpr u32 PSF_MAGIC = 0x00505346;
17constexpr u32 PSF_VERSION_1_1 = 0x00000101;
18constexpr u32 PSF_VERSION_1_0 = 0x00000100;
19
20struct PSFHeader {
21 u32_be magic;
22 u32_le version;
23 u32_le key_table_offset;
24 u32_le data_table_offset;
25 u32_le index_table_entries;
26};
27static_assert(sizeof(PSFHeader) == 0x14);
28
29struct PSFRawEntry {
30 u16_le key_offset;
31 u16_be param_fmt;
32 u32_le param_len;
33 u32_le param_max_len;
34 u32_le data_offset;
35};
36static_assert(sizeof(PSFRawEntry) == 0x10);
37
38enum class PSFEntryFmt : u16 {
39 Binary = 0x0004, // Binary data
40 Text = 0x0204, // String in UTF-8 format and NULL terminated
41 Integer = 0x0404, // Signed 32-bit integer
42};
43
44class PSF {
45 struct Entry {
46 std::string key;
47 PSFEntryFmt param_fmt;
48 u32 max_len;
49 };
50
51public:
52 PSF() = default;
53 ~PSF() = default;
54
55 PSF(const PSF& other) = default;
56 PSF(PSF&& other) noexcept = default;
57 PSF& operator=(const PSF& other) = default;
58 PSF& operator=(PSF&& other) noexcept = default;
59
60 bool Open(const std::filesystem::path& filepath);
61 bool Open(const std::vector<u8>& psf_buffer);
62
63 [[nodiscard]] std::vector<u8> Encode() const;
64 void Encode(std::vector<u8>& buf) const;
65 bool Encode(const std::filesystem::path& filepath) const;
66
67 std::optional<std::span<const u8>> GetBinary(std::string_view key) const;
68 std::optional<std::string_view> GetString(std::string_view key) const;
69 std::optional<s32> GetInteger(std::string_view key) const;
70
71 void AddBinary(std::string key, std::vector<u8> value, bool update = false);
72 void AddBinary(std::string key, uint64_t value, bool update = false); // rsv4 format
73 void AddString(std::string key, std::string value, bool update = false);
74 void AddInteger(std::string key, s32 value, bool update = false);
75
76 [[nodiscard]] std::chrono::system_clock::time_point GetLastWrite() const {
77 return last_write;
78 }
79
80 [[nodiscard]] const std::vector<Entry>& GetEntries() const {
81 return entry_list;
82 }
83
84private:
85 mutable std::chrono::system_clock::time_point last_write;
86
87 std::vector<Entry> entry_list;
88
89 std::unordered_map<size_t, std::vector<u8>> map_binaries;
90 std::unordered_map<size_t, std::string> map_strings;
91 std::unordered_map<size_t, s32> map_integers;
92
93 [[nodiscard]] std::pair<std::vector<Entry>::iterator, size_t> FindEntry(std::string_view key);
94 [[nodiscard]] std::pair<std::vector<Entry>::const_iterator, size_t> FindEntry(
95 std::string_view key) const;
96};
97