Skip to content

Commit 0f5c102

Browse files
vegetass4sithlord48
authored andcommitted
Initial PS4 file support
First phase PS4 compatibility
1 parent e27dc3f commit 0f5c102

File tree

12 files changed

+144
-9
lines changed

12 files changed

+144
-9
lines changed

src/data/FF7Save.cpp

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,29 @@ FF7SaveInfo::FORMAT FF7Save::fileDataFormat(QFile &file)
6161
: QStringLiteral("Unknown"));
6262
return FF7SaveInfo::FORMAT::UNKNOWN;
6363
}
64+
if ( (file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PS4)) && file.peek(0x00B0 + FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).mid(0x00B0,FF7SaveInfo::get()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()) == FF7SaveInfo::get()->fileIdentifier(FF7SaveInfo::FORMAT::PS4)) {
65+
QTextStream(stdout)
66+
<< "[FF7Save::loadFile] PS4 Save "
67+
<< file.peek(0x00B0+FF7SaveInfo::get()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).mid(0x00B0,FF7SaveInfo::get()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).toHex( )
68+
<< "\n";
69+
QFile ps4binfile(QFileInfo(file).path() + "/" + QFileInfo(file).fileName() + ".bin");//QFileInfo(file).baseName()
70+
if (!ps4binfile.open(QIODevice::ReadOnly)) {
71+
QTextStream(stdout) << "[FF7Save::loadFile] PS4 BIN File error: missing file: " << QFileInfo(ps4binfile).absoluteFilePath();
72+
return FF7SaveInfo::FORMAT::UNKNOWN;
73+
} else {
74+
QTextStream(stdout) << "[FF7Save::loadFile] PS4 BIN File loaded: " << QFileInfo(ps4binfile).absoluteFilePath() << "\n";
75+
if(ps4binfile.size() == FF7SaveInfo::get()->fileSize(FF7SaveInfo::FORMAT::PS4BIN) && (ps4binfile.peek(FF7SaveInfo::fileHeaderSize(FF7SaveInfo::FORMAT::PS4BIN)) == FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PS4BIN))) {
76+
auto ps4bin = ps4binfile.readAll();
77+
m_ps4_iv = ps4bin.mid(0x10, 0x10);
78+
m_ps4_key = ps4bin.mid(0x20, 0x10);
79+
QTextStream(stdout)
80+
<< "[FF7Save::loadFile] PS4 BIN File Size: " << FF7SaveInfo::get()->fileSize(FF7SaveInfo::FORMAT::PS4BIN) << "\n"
81+
<< "[FF7Save::loadFile] PS4 BIN pfsSKKey IV: " << m_ps4_iv.toHex() << "\n"
82+
<< "[FF7Save::loadFile] PS4 BIN pfsSKKey KEY: " << m_ps4_key.toHex() << "\n";
83+
setFormat(FF7SaveInfo::FORMAT::PS4);
84+
}
85+
}
86+
}
6487
if ((file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSP)) && (file.peek(25)).startsWith(FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PSP)))
6588
return FF7SaveInfo::FORMAT::PSP;
6689
if ((file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::VGS)) && (file.peek(25)).startsWith(FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::VGS)))
@@ -913,7 +936,8 @@ char FF7Save::psx_block_type(int s)
913936
case FF7SaveInfo::FORMAT::PC:
914937
case FF7SaveInfo::FORMAT::SWITCH:
915938
case FF7SaveInfo::FORMAT::PSX:
916-
case FF7SaveInfo::FORMAT::PS3: return 0x00;
939+
case FF7SaveInfo::FORMAT::PS3:
940+
case FF7SaveInfo::FORMAT::PS4: return 0x00;
917941
case FF7SaveInfo::FORMAT::PGE: return _fileHeader.at(0);
918942
default:
919943
int index = 128 + (128 * s);
@@ -930,7 +954,8 @@ void FF7Save::setPsx_block_type(int s, char block_type)
930954
case FF7SaveInfo::FORMAT::PC:
931955
case FF7SaveInfo::FORMAT::SWITCH:
932956
case FF7SaveInfo::FORMAT::PSX:
933-
case FF7SaveInfo::FORMAT::PS3: return;
957+
case FF7SaveInfo::FORMAT::PS3:
958+
case FF7SaveInfo::FORMAT::PS4: return;
934959
case FF7SaveInfo::FORMAT::PGE: _fileHeader.replace(0, 1, QByteArray(1, block_type)); break;
935960
default:
936961
int index = 128 + (128 * s);
@@ -950,7 +975,8 @@ void FF7Save::setPsx_block_next(int s, int next)
950975
case FF7SaveInfo::FORMAT::PC:
951976
case FF7SaveInfo::FORMAT::SWITCH:
952977
case FF7SaveInfo::FORMAT::PSX:
953-
case FF7SaveInfo::FORMAT::PS3: return;
978+
case FF7SaveInfo::FORMAT::PS3:
979+
case FF7SaveInfo::FORMAT::PS4: return;
954980
case FF7SaveInfo::FORMAT::PGE: _fileHeader.replace(8, 1, QByteArray(1, next)); break;
955981
default:
956982
int index = 128 + (128 * s);
@@ -967,7 +993,8 @@ quint8 FF7Save::psx_block_next(int s)
967993
case FF7SaveInfo::FORMAT::PC:
968994
case FF7SaveInfo::FORMAT::SWITCH:
969995
case FF7SaveInfo::FORMAT::PSX:
970-
case FF7SaveInfo::FORMAT::PS3: return 0x00;
996+
case FF7SaveInfo::FORMAT::PS3:
997+
case FF7SaveInfo::FORMAT::PS4: return 0x00;
971998
case FF7SaveInfo::FORMAT::PGE: return quint8(_fileHeader.at(0x08));
972999
default:
9731000
int index = 128 + (128 * s);
@@ -984,7 +1011,8 @@ void FF7Save::setPsx_block_size(int s, int blockSize)
9841011
case FF7SaveInfo::FORMAT::PC:
9851012
case FF7SaveInfo::FORMAT::SWITCH:
9861013
case FF7SaveInfo::FORMAT::PSX:
987-
case FF7SaveInfo::FORMAT::PS3: return;
1014+
case FF7SaveInfo::FORMAT::PS3:
1015+
case FF7SaveInfo::FORMAT::PS4: return;
9881016
default: break;
9891017
}
9901018

@@ -1007,6 +1035,7 @@ quint8 FF7Save::psx_block_size(int s)
10071035
switch (fileFormat) {
10081036
case FF7SaveInfo::FORMAT::UNKNOWN:
10091037
case FF7SaveInfo::FORMAT::PC:
1038+
case FF7SaveInfo::FORMAT::PS4:
10101039
case FF7SaveInfo::FORMAT::SWITCH: return 1;
10111040
case FF7SaveInfo::FORMAT::PSX: return quint8(QFile(fileName()).size() / FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSX));
10121041
case FF7SaveInfo::FORMAT::PS3: return quint8((QFile(fileName()).size() - 0x84) / FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSX));

src/data/FF7Save.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,8 @@ class FF7TKDATA_EXPORT FF7Save: public QObject
10421042
bool fileHasChanged;
10431043
QString buffer_region; // hold the buffers region data.
10441044
QList<QString> SG_Region_String;
1045+
QByteArray m_ps4_iv;
1046+
QByteArray m_ps4_key;
10451047
QString filename;//opened file
10461048
QVector< SubContainer > parseXML(const QString &fileName, const QString &metadataPath, const QString &UserID);
10471049
QVector< SubContainer > createMetadata(const QString &fileName, const QString &UserID);

src/data/FF7SaveInfo.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ int FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT format)
3030
case FORMAT::VMC: return get()->d->VMC_FILE_SIZE;
3131
case FORMAT::PSP: return get()->d->PSP_FILE_SIZE;
3232
case FORMAT::PS3: return get()->d->PS3_FILE_SIZE;
33+
case FORMAT::PS4: return get()->d->PS4_FILE_SIZE;
34+
case FORMAT::PS4BIN: return get()->d->PS4_BINFILE_SIZE;
3335
case FORMAT::DEX: return get()->d->DEX_FILE_SIZE;
3436
case FORMAT::VGS: return get()->d->VGS_FILE_SIZE;
3537
case FORMAT::SWITCH: return get()->d->SWITCH_FILE_SIZE;
@@ -46,6 +48,8 @@ int FF7SaveInfo::fileHeaderSize(FF7SaveInfo::FORMAT format)
4648
case FORMAT::VMC: return get()->d->VMC_FILE_HEADER_SIZE;
4749
case FORMAT::PSP: return get()->d->PSP_FILE_HEADER_SIZE;
4850
case FORMAT::PS3: return get()->d->PS3_FILE_HEADER_SIZE;
51+
case FORMAT::PS4: return get()->d->PS4_FILE_HEADER_SIZE;
52+
case FORMAT::PS4BIN: return get()->d->PS4_BINFILE_FILE_ID_SIZE;
4953
case FORMAT::DEX: return get()->d->DEX_FILE_HEADER_SIZE;
5054
case FORMAT::VGS: return get()->d->VGS_FILE_HEADER_SIZE;
5155
case FORMAT::SWITCH: return get()->d->SWITCH_FILE_HEADER_SIZE;
@@ -62,6 +66,7 @@ int FF7SaveInfo::slotHeaderSize(FF7SaveInfo::FORMAT format)
6266
case FORMAT::VMC:
6367
case FORMAT::PSP:
6468
case FORMAT::PS3:
69+
case FORMAT::PS4:
6570
case FORMAT::DEX:
6671
case FORMAT::PGE:
6772
case FORMAT::PDA:
@@ -77,6 +82,7 @@ int FF7SaveInfo::slotFooterSize(FF7SaveInfo::FORMAT format)
7782
case FORMAT::VMC:
7883
case FORMAT::PSP:
7984
case FORMAT::PS3:
85+
case FORMAT::PS4:
8086
case FORMAT::DEX:
8187
case FORMAT::PGE:
8288
case FORMAT::PDA:
@@ -91,7 +97,8 @@ int FF7SaveInfo::slotCount(FF7SaveInfo::FORMAT format)
9197
case FORMAT::PDA:
9298
case FORMAT::PGE:
9399
case FORMAT::PSX:
94-
case FORMAT::PS3: return 1;
100+
case FORMAT::PS3:
101+
case FORMAT::PS4: return 1;
95102
case FORMAT::VMC:
96103
case FORMAT::PSP:
97104
case FORMAT::DEX:
@@ -110,6 +117,8 @@ QByteArray FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT format)
110117
case FORMAT::VMC: return get()->d->VMC_FILE_ID;
111118
case FORMAT::PSP: return get()->d->PSP_FILE_ID;
112119
case FORMAT::PS3: return get()->d->PS3_FILE_ID;
120+
case FORMAT::PS4: return get()->d->PS4_FILE_ID;
121+
case FORMAT::PS4BIN: return get()->d->PS4_BINFILE_FILE_ID;
113122
// case FORMAT::DEX: return get()->d->DEX_FILE_ID;
114123
case FORMAT::VGS: return get()->d->VGS_FILE_ID;
115124
case FORMAT::SWITCH: return get()->d->SWITCH_FILE_ID;
@@ -127,6 +136,7 @@ QByteArray FF7SaveInfo::fileHeader(FF7SaveInfo::FORMAT format)
127136
case FORMAT::VMC: return QByteArray(fileIdentifier(format)).append(fileHeaderSize(format) - fileIdentifier(format).length(), 0x00);
128137
case FORMAT::PSP: return get()->d->PSP_FILE_HEADER;
129138
case FORMAT::PS3: return get()->d->PS3_FILE_HEADER;
139+
case FORMAT::PS4: return get()->d->PS4_FILE_HEADER;
130140
default: return QByteArray();
131141
}
132142
}
@@ -140,6 +150,7 @@ QByteArray FF7SaveInfo::slotHeader(FF7SaveInfo::FORMAT format, int slot)
140150
case FORMAT::PSX:
141151
case FORMAT::PSP:
142152
case FORMAT::PS3:
153+
case FORMAT::PS4:
143154
case FORMAT::DEX:
144155
case FORMAT::VGS:
145156
case FORMAT::VMC: return QByteArray(get()->d->PSX_SLOT_HEADER.at(slot)).append(256, 0x00);
@@ -155,6 +166,7 @@ QByteArray FF7SaveInfo::slotFooter(FF7SaveInfo::FORMAT format)
155166
case FORMAT::PSX:
156167
case FORMAT::PSP:
157168
case FORMAT::PS3:
169+
case FORMAT::PS4:
158170
case FORMAT::DEX:
159171
case FORMAT::VGS:
160172
case FORMAT::VMC: return QByteArray(get()->d->PSX_SLOT_FOOTER_SIZE, 0x00);
@@ -167,6 +179,7 @@ QByteArray FF7SaveInfo::signingKey(FF7SaveInfo::FORMAT format)
167179
switch (format) {
168180
case FORMAT::PSP:
169181
case FORMAT::PS3: return get()->d->PS_SIGNING_KEY;
182+
case FORMAT::PS4: return get()->d->PS4_SIGNING_KEY;
170183
default: return QByteArray();
171184
}
172185
}
@@ -187,6 +200,7 @@ QByteArray FF7SaveInfo::signingIV(FF7SaveInfo::FORMAT format)
187200
switch (format) {
188201
case FORMAT::PSP:
189202
case FORMAT::PS3: return get()->d->PS_SIGNING_IV;
203+
case FORMAT::PS4: return get()->d->PS4_SIGNING_IV;
190204
default: return QByteArray();
191205
}
192206
}
@@ -196,6 +210,7 @@ int FF7SaveInfo::fileSeedOffset(FF7SaveInfo::FORMAT format)
196210
switch (format) {
197211
case FORMAT::PSP: return get()->d->PSP_SEED_OFFSET;
198212
case FORMAT::PS3: return get()->d->PS3_SEED_OFFSET;
213+
case FORMAT::PS4: return get()->d->PS4_SEED_OFFSET;
199214
default: return -1;
200215
}
201216
}
@@ -205,6 +220,7 @@ int FF7SaveInfo::fileSignatureOffset(FF7SaveInfo::FORMAT format)
205220
switch (format) {
206221
case FORMAT::PSP: return get()->d->PSP_SIGNATURE_OFFSET;
207222
case FORMAT::PS3: return get()->d->PS3_SIGNATURE_OFFSET;
223+
case FORMAT::PS4: return get()->d->PS4_SIGNATURE_OFFSET;
208224
default: return -1;
209225
}
210226
}
@@ -214,6 +230,7 @@ int FF7SaveInfo::fileSignatureSize(FF7SaveInfo::FORMAT format)
214230
switch (format) {
215231
case FORMAT::PSP:
216232
case FORMAT::PS3: return get()->d->PS_SIGNATURE_SIZE;
233+
case FORMAT::PS4: return get()->d->PS4_SIGNATURE_SIZE;
217234
default: return 0;
218235
}
219236
}
@@ -230,6 +247,7 @@ QRegularExpression FF7SaveInfo::validNames(FF7SaveInfo::FORMAT format)
230247
case FORMAT::PSX: return get()->d->PSX_VALID_NAME_REGEX;
231248
case FORMAT::PSP: return get()->d->PSP_VALID_NAME_REGEX;
232249
case FORMAT::PS3: return get()->d->PS3_VALID_NAME_REGEX;
250+
case FORMAT::PS4: return get()->d->PS4_VALID_NAME_REGEX;
233251
case FORMAT::DEX: return get()->d->DEX_VALID_NAME_REGEX;
234252
case FORMAT::VGS: return get()->d->VGS_VALID_NAME_REGEX;
235253
case FORMAT::VMC: return get()->d->VMC_VALID_NAME_REGEX;
@@ -247,6 +265,7 @@ QString FF7SaveInfo::typeDescription(FF7SaveInfo::FORMAT format)
247265
case FORMAT::PSX: return tr(get()->d->PSX_FILE_DESCRIPTION.toUtf8());
248266
case FORMAT::PSP: return tr(get()->d->PSP_FILE_DESCRIPTION.toUtf8());
249267
case FORMAT::PS3: return tr(get()->d->PS3_FILE_DESCRIPTION.toUtf8());
268+
case FORMAT::PS4: return tr(get()->d->PS4_FILE_DESCRIPTION.toUtf8());
250269
case FORMAT::DEX: return tr(get()->d->DEX_FILE_DESCRIPTION.toUtf8());
251270
case FORMAT::VGS: return tr(get()->d->VGS_FILE_DESCRIPTION.toUtf8());
252271
case FORMAT::VMC: return tr(get()->d->VMC_FILE_DESCRIPTION.toUtf8());
@@ -264,6 +283,7 @@ QStringList FF7SaveInfo::typeExtension(FF7SaveInfo::FORMAT format)
264283
case FORMAT::PSX: return get()->d->PSX_VALID_EXTENSIONS;
265284
case FORMAT::PSP: return get()->d->PSP_VALID_EXTENSIONS;
266285
case FORMAT::PS3: return get()->d->PS3_VALID_EXTENSIONS;
286+
case FORMAT::PS4: return get()->d->PS4_VALID_EXTENSIONS;
267287
case FORMAT::DEX: return get()->d->DEX_VALID_EXTENSIONS;
268288
case FORMAT::VGS: return get()->d->VGS_VALID_EXTENSIONS;
269289
case FORMAT::VMC: return get()->d->VMC_VALID_EXTENSIONS;
@@ -284,25 +304,27 @@ QString FF7SaveInfo::typeFilter(FF7SaveInfo::FORMAT format)
284304
QString FF7SaveInfo::knownTypesFilter()
285305
{
286306
QString space = QStringLiteral(" ");
287-
QString allTypes = QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10")
307+
QString allTypes = QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11")
288308
.arg(get()->d->PC_VALID_EXTENSIONS.join(space)
289309
, get()->d->PSX_VALID_EXTENSIONS.join(space)
290310
, get()->d->PSP_VALID_EXTENSIONS.join(space)
291311
, get()->d->PS3_VALID_EXTENSIONS.join(space)
312+
, get()->d->PS4_VALID_EXTENSIONS.join(space)
292313
, get()->d->DEX_VALID_EXTENSIONS.join(space)
293314
, get()->d->VGS_VALID_EXTENSIONS.join(space)
294315
, get()->d->VMC_VALID_EXTENSIONS.join(space)
295316
, get()->d->SWITCH_VALID_EXTENSIONS.join(space)
296317
, get()->d->PGE_VALID_EXTENSIONS.join(space)
297318
, get()->d->PDA_VALID_EXTENSIONS.join(space));
298319

299-
return QStringLiteral("%1;;%2;;%3;;%4;;%5;;%6;;%7;;%8;;%9;;%10;;%11;;%12")
320+
return QStringLiteral("%1;;%2;;%3;;%4;;%5;;%6;;%7;;%8;;%9;;%10;;%11;;%12;;%13")
300321
.arg(tr("Known FF7 Save Types (%1)").arg(allTypes)
301322
, typeFilter(FORMAT::PC)
302323
, typeFilter(FORMAT::SWITCH)
303324
, typeFilter(FORMAT::VMC)
304325
, typeFilter(FORMAT::PSX)
305326
, typeFilter(FORMAT::PS3)
327+
, typeFilter(FORMAT::PS4)
306328
, typeFilter(FORMAT::PSP)
307329
, typeFilter(FORMAT::DEX)
308330
, typeFilter(FORMAT::VGS)
@@ -315,6 +337,7 @@ bool FF7SaveInfo::isTypePC(FF7SaveInfo::FORMAT format)
315337
{
316338
switch(format) {
317339
case FORMAT::SWITCH:
340+
case FORMAT::PS4:
318341
case FORMAT::PC: return true;
319342
default: return false;
320343
};
@@ -368,4 +391,3 @@ QByteArray FF7SaveInfo::defaultSaveData()
368391
{
369392
return get()->d->DEFAULT_SAVE;
370393
}
371-

src/data/FF7SaveInfo.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33

44
#pragma once
55

6+
#ifdef _MSC_VER
7+
# define PACK(structure) \
8+
__pragma(pack(push, 1)) \
9+
structure \
10+
__pragma(pack(pop))
11+
#elif defined(__MINGW32__)
12+
#define PACK(structure) structure __attribute__ ((gcc_struct, __packed__))
13+
#else
14+
#define PACK(structure) structure Q_PACKED
15+
#endif
16+
617
#include <QObject>
718
#include <QRegularExpression>
819
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
@@ -36,6 +47,8 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
3647
SWITCH = 7, //!< Switch Format
3748
PGE = 8, //!< Psx Game Edit Style Single Save
3849
PDA = 9, //!< GS , Dantel Style Save
50+
PS4 = 10, //!< PS4 Save Format
51+
PS4BIN = 11 //!< PS4 BIN File (pfsSKKey)
3952
};
4053
Q_ENUM(FORMAT)
4154

@@ -63,6 +76,21 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
6376
};
6477
Q_ENUM(PSVINFO)
6578

79+
/**
80+
* \struct pfsSKKey
81+
* \brief Extra bin file (Sealedkey) used for PS4 format
82+
*/
83+
PACK(
84+
struct pfsSKKey {
85+
quint8 MAGIC[8]; /**< [0x0000] MAGIC (0x08) */
86+
quint16 KEYSET; /**< [0x0008] KEYSET (0x02) */
87+
quint8 pad[6]; /**< [0x000A] Padding zeros (0x06) */
88+
quint8 IV[16]; /**< [0x0010] AES IV (0x10) */
89+
quint8 KEY[32]; /**< [0x0020] AES KEY (0x20) */
90+
quint8 SHA256[32]; /**< [0x0040] AES SHA256 (0x20) */
91+
}
92+
);
93+
6694
/**
6795
* @brief Get the FF7SaveInfo Instance.
6896
*/
@@ -325,6 +353,28 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
325353
inline static const int PS_SIGNATURE_SIZE = 0x0014;
326354
inline static const QByteArray PS_SIGNING_KEY= QByteArray::fromRawData("\xAB\x5A\xBC\x9F\xC1\xF4\x9D\xE6\xA0\x51\xDB\xAE\xFA\x51\x88\x59", 0x10);
327355
inline static const QByteArray PS_SIGNING_IV= QByteArray::fromRawData("\xB3\x0F\xFE\xED\xB7\xDC\x5E\xB7\x13\x3D\xA6\x0D\x1B\x6B\x2C\xDC", 0x10);
356+
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PS4 SAVE INFO~~~~~~~~~~~~~~~~~~~~~~~~~*/
357+
static const int PS4_FILE_SIZE = 0xA00000;
358+
static const int PS4_FILE_HEADER_SIZE = 0x00AF;
359+
inline static const QString PS4_FILE_DESCRIPTION = QT_TR_NOOP("PS4 Save File");
360+
inline static const QStringList PS4_VALID_EXTENSIONS { QStringLiteral("*.ff7") };
361+
inline static const QRegularExpression PS4_VALID_NAME_REGEX = QRegularExpression(QStringLiteral("save0[0-9].ff7"));
362+
inline static const QByteArray PS4_FILE_ID = QByteArray::fromRawData("\x17\x00\x00\x00\x00\x00\x00\x00", 8);
363+
inline static const QByteArray PS4_BINFILE_FILE_ID = QByteArray::fromRawData("\x70\x66\x73\x53\x4B\x4B\x65\x79", 8);
364+
static const int PS4_BINFILE_FILE_ID_SIZE = 8;
365+
static const int PS4_BINFILE_SIZE = 0x60;
366+
static const int PS4_BINFILE_IV_OFFSET= 0x10;
367+
static const int PS4_BINFILE_IV_SIZE= 0x10;
368+
static const int PS4_SEED_OFFSET = 0x0008;
369+
static const int PS4_SIGNATURE_OFFSET = 0x001C;
370+
static const int PS4_FILE_TYPE_OFFSET = 0x0038;
371+
static const int PS4_FILE_DISP_SIZE_OFFSET = 0x0040;
372+
static const int PS4_FILE_SIZE_OFFSET = 0x005C;
373+
inline static const QByteArray PS4_FILE_HEADER = QByteArray::fromRawData("\x00\x56\x53\x50\x00\x00\x00\x00\x04\xbc\x97\x58\x11\x0f\x7e\x85\xc7\x4f\x2f\xd0\x5a\x28\xb6\x25\xe6\x9a\x6e\xa1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x20\x00\x00\x84\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x03\x90\x00\x00\x42\x41\x53\x43\x55\x53\x2d\x39\x34\x31\x36\x33\x46\x46\x37\x2d\x53\x30\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", PS3_FILE_HEADER_SIZE);
374+
/*~~~~~~~ PS4 Signing ~~~~~~~~~~~~~~*/
375+
static const int PS4_SIGNATURE_SIZE = 0x0014;
376+
inline static const QByteArray PS4_SIGNING_KEY= QByteArray::fromRawData("\xAB\x5A\xBC\x9F\xC1\xF4\x9D\xE6\xA0\x51\xDB\xAE\xFA\x51\x88\x59", 0x10);
377+
inline static const QByteArray PS4_SIGNING_IV= QByteArray::fromRawData("\xB3\x0F\xFE\xED\xB7\xDC\x5E\xB7\x13\x3D\xA6\x0D\x1B\x6B\x2C\xDC", 0x10);
328378
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Mem Card Format~~~~~~~~~~~~~~~~~~~*/
329379
inline static const int VMC_FILE_SIZE = 0x20000;
330380
inline static const int VMC_FILE_HEADER_SIZE = 0x2000;

translations/ff7tk_de.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6943,6 +6943,10 @@ Die km / h beschleunigt berechnet werden während des Spielens </translation>
69436943
<source>XP AR GS Caetla SmartLink Dantel</source>
69446944
<translation type="unfinished">XP AR GS Caetla SmartLink Dantel</translation>
69456945
</message>
6946+
<message>
6947+
<source>PS4 Save File</source>
6948+
<translation type="unfinished">PS4 Spielstand</translation>
6949+
</message>
69466950
</context>
69476951
<context>
69486952
<name>ItemPreview</name>

translations/ff7tk_en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6943,6 +6943,10 @@ The km/h speeds are calculated while playing </translation>
69436943
<source>XP AR GS Caetla SmartLink Dantel</source>
69446944
<translation>XP AR GS Caetla SmartLink Dantel</translation>
69456945
</message>
6946+
<message>
6947+
<source>PS4 Save File</source>
6948+
<translation>PS4 Save File</translation>
6949+
</message>
69466950
</context>
69476951
<context>
69486952
<name>ItemPreview</name>

translations/ff7tk_es.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6943,6 +6943,10 @@ Los km/h son calculados mientras se juega </translation>
69436943
<source>XP AR GS Caetla SmartLink Dantel</source>
69446944
<translation type="unfinished">XP AR GS Caetla SmartLink Dantel</translation>
69456945
</message>
6946+
<message>
6947+
<source>PS4 Save File</source>
6948+
<translation type="unfinished">Partida Guardada PS4</translation>
6949+
</message>
69466950
</context>
69476951
<context>
69486952
<name>ItemPreview</name>

0 commit comments

Comments
 (0)