Seregon/ShadPKG

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

C++/47.3 KB/No license
common/shadpkg_endian.h
ShadPKG / common / shadpkg_endian.h
1// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3 
4/**
5 * (c) 2014-2016 Alexandro Sanchez Bach. All rights reserved.
6 * Released under GPL v2 license. Read LICENSE for more details.
7 * Some modifications for using with shadps4 by georgemoralis
8 */
9 
10#pragma once
11 
12#include <bit>
13#include <concepts>
14#include "common/shadpkg_types.h"
15#include <fmt/format.h>
16 
17namespace Common {
18 
19/**
20 * Native endianness
21 */
22template <typename T>
23using NativeEndian = T;
24 
25template <std::integral T>
26class SwappedEndian {
27public:
28 const T& Raw() const {
29 return data;
30 }
31 
32 T Swap() const {
33 return std::byteswap(data);
34 }
35 
36 void FromRaw(const T& value) {
37 data = value;
38 }
39 
40 void FromSwap(const T& value) {
41 data = std::byteswap(value);
42 }
43 
44 operator const T() const {
45 return Swap();
46 }
47 
48 template <typename T1>
49 explicit operator const SwappedEndian<T1>() const {
50 SwappedEndian<T1> res;
51 if (sizeof(T1) < sizeof(T)) {
52 res.FromRaw(Raw() >> ((sizeof(T) - sizeof(T1)) * 8));
53 } else if (sizeof(T1) > sizeof(T)) {
54 res.FromSwap(Swap());
55 } else {
56 res.FromRaw(Raw());
57 }
58 return res;
59 }
60 
61 SwappedEndian<T>& operator=(const T& right) {
62 FromSwap(right);
63 return *this;
64 }
65 SwappedEndian<T>& operator=(const SwappedEndian<T>& right) = default;
66 
67 template <typename T1>
68 SwappedEndian<T>& operator+=(T1 right) {
69 return *this = T(*this) + right;
70 }
71 template <typename T1>
72 SwappedEndian<T>& operator-=(T1 right) {
73 return *this = T(*this) - right;
74 }
75 template <typename T1>
76 SwappedEndian<T>& operator*=(T1 right) {
77 return *this = T(*this) * right;
78 }
79 template <typename T1>
80 SwappedEndian<T>& operator/=(T1 right) {
81 return *this = T(*this) / right;
82 }
83 template <typename T1>
84 SwappedEndian<T>& operator%=(T1 right) {
85 return *this = T(*this) % right;
86 }
87 template <typename T1>
88 SwappedEndian<T>& operator&=(T1 right) {
89 return *this = T(*this) & right;
90 }
91 template <typename T1>
92 SwappedEndian<T>& operator|=(T1 right) {
93 return *this = T(*this) | right;
94 }
95 template <typename T1>
96 SwappedEndian<T>& operator^=(T1 right) {
97 return *this = T(*this) ^ right;
98 }
99 template <typename T1>
100 SwappedEndian<T>& operator<<=(T1 right) {
101 return *this = T(*this) << right;
102 }
103 template <typename T1>
104 SwappedEndian<T>& operator>>=(T1 right) {
105 return *this = T(*this) >> right;
106 }
107 
108 template <typename T1>
109 SwappedEndian<T>& operator+=(const SwappedEndian<T1>& right) {
110 return *this = Swap() + right.Swap();
111 }
112 template <typename T1>
113 SwappedEndian<T>& operator-=(const SwappedEndian<T1>& right) {
114 return *this = Swap() - right.Swap();
115 }
116 template <typename T1>
117 SwappedEndian<T>& operator*=(const SwappedEndian<T1>& right) {
118 return *this = Swap() * right.Swap();
119 }
120 template <typename T1>
121 SwappedEndian<T>& operator/=(const SwappedEndian<T1>& right) {
122 return *this = Swap() / right.Swap();
123 }
124 template <typename T1>
125 SwappedEndian<T>& operator%=(const SwappedEndian<T1>& right) {
126 return *this = Swap() % right.Swap();
127 }
128 template <typename T1>
129 SwappedEndian<T>& operator&=(const SwappedEndian<T1>& right) {
130 return *this = Raw() & right.Raw();
131 }
132 template <typename T1>
133 SwappedEndian<T>& operator|=(const SwappedEndian<T1>& right) {
134 return *this = Raw() | right.Raw();
135 }
136 template <typename T1>
137 SwappedEndian<T>& operator^=(const SwappedEndian<T1>& right) {
138 return *this = Raw() ^ right.Raw();
139 }
140 
141 template <typename T1>
142 SwappedEndian<T> operator&(const SwappedEndian<T1>& right) const {
143 return SwappedEndian<T>{Raw() & right.Raw()};
144 }
145 template <typename T1>
146 SwappedEndian<T> operator|(const SwappedEndian<T1>& right) const {
147 return SwappedEndian<T>{Raw() | right.Raw()};
148 }
149 template <typename T1>
150 SwappedEndian<T> operator^(const SwappedEndian<T1>& right) const {
151 return SwappedEndian<T>{Raw() ^ right.Raw()};
152 }
153 
154 template <typename T1>
155 bool operator==(T1 right) const {
156 return (T1)Swap() == right;
157 }
158 template <typename T1>
159 bool operator!=(T1 right) const {
160 return !(*this == right);
161 }
162 template <typename T1>
163 bool operator>(T1 right) const {
164 return (T1)Swap() > right;
165 }
166 template <typename T1>
167 bool operator<(T1 right) const {
168 return (T1)Swap() < right;
169 }
170 template <typename T1>
171 bool operator>=(T1 right) const {
172 return (T1)Swap() >= right;
173 }
174 template <typename T1>
175 bool operator<=(T1 right) const {
176 return (T1)Swap() <= right;
177 }
178 
179 template <typename T1>
180 bool operator==(const SwappedEndian<T1>& right) const {
181 return Raw() == right.Raw();
182 }
183 template <typename T1>
184 bool operator!=(const SwappedEndian<T1>& right) const {
185 return !(*this == right);
186 }
187 template <typename T1>
188 bool operator>(const SwappedEndian<T1>& right) const {
189 return (T1)Swap() > right.Swap();
190 }
191 template <typename T1>
192 bool operator<(const SwappedEndian<T1>& right) const {
193 return (T1)Swap() < right.Swap();
194 }
195 template <typename T1>
196 bool operator>=(const SwappedEndian<T1>& right) const {
197 return (T1)Swap() >= right.Swap();
198 }
199 template <typename T1>
200 bool operator<=(const SwappedEndian<T1>& right) const {
201 return (T1)Swap() <= right.Swap();
202 }
203 
204 SwappedEndian<T> operator++(int) {
205 SwappedEndian<T> res = *this;
206 *this += 1;
207 return res;
208 }
209 SwappedEndian<T> operator--(int) {
210 SwappedEndian<T> res = *this;
211 *this -= 1;
212 return res;
213 }
214 SwappedEndian<T>& operator++() {
215 *this += 1;
216 return *this;
217 }
218 SwappedEndian<T>& operator--() {
219 *this -= 1;
220 return *this;
221 }
222 
223private:
224 T data;
225};
226 
227template <typename T>
228using LittleEndian = std::conditional_t<std::endian::native == std::endian::little, NativeEndian<T>,
229 SwappedEndian<T>>;
230 
231template <typename T>
232using BigEndian =
233 std::conditional_t<std::endian::native == std::endian::big, NativeEndian<T>, SwappedEndian<T>>;
234 
235} // namespace Common
236 
237using u16_be = Common::BigEndian<u16>;
238using u32_be = Common::BigEndian<u32>;
239using u64_be = Common::BigEndian<u64>;
240 
241using u16_le = Common::LittleEndian<u16>;
242using u32_le = Common::LittleEndian<u32>;
243using u64_le = Common::LittleEndian<u64>;
244 
245template <std::integral T>
246struct fmt::formatter<Common::SwappedEndian<T>> : fmt::formatter<T> {
247 auto format(const Common::SwappedEndian<T>& val, fmt::format_context& ctx) const {
248 return fmt::formatter<T>::format(static_cast<T>(val), ctx);
249 }
250};
251 
252