Skip to content

Commit 5723f2b

Browse files
vegetass4sithlord48
authored andcommitted
Initial PS4 file support
First phase PS4 compatibility
1 parent 4c44590 commit 5723f2b

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
@@ -64,6 +64,29 @@ FF7SaveInfo::FORMAT FF7Save::fileDataFormat(QFile &file)
6464
return FF7SaveInfo::FORMAT::UNKNOWN;
6565
}
6666
}
67+
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)) {
68+
QTextStream(stdout)
69+
<< "[FF7Save::loadFile] PS4 Save "
70+
<< file.peek(0x00B0+FF7SaveInfo::get()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).mid(0x00B0,FF7SaveInfo::get()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).toHex( )
71+
<< "\n";
72+
QFile ps4binfile(QFileInfo(file).path() + "/" + QFileInfo(file).fileName() + ".bin");//QFileInfo(file).baseName()
73+
if (!ps4binfile.open(QIODevice::ReadOnly)) {
74+
QTextStream(stdout) << "[FF7Save::loadFile] PS4 BIN File error: missing file: " << QFileInfo(ps4binfile).absoluteFilePath();
75+
return FF7SaveInfo::FORMAT::UNKNOWN;
76+
} else {
77+
QTextStream(stdout) << "[FF7Save::loadFile] PS4 BIN File loaded: " << QFileInfo(ps4binfile).absoluteFilePath() << "\n";
78+
if(ps4binfile.size() == FF7SaveInfo::get()->fileSize(FF7SaveInfo::FORMAT::PS4BIN) && (ps4binfile.peek(FF7SaveInfo::fileHeaderSize(FF7SaveInfo::FORMAT::PS4BIN)) == FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PS4BIN))) {
79+
auto ps4bin = ps4binfile.readAll();
80+
m_ps4_iv = ps4bin.mid(0x10, 0x10);
81+
m_ps4_key = ps4bin.mid(0x20, 0x10);
82+
QTextStream(stdout)
83+
<< "[FF7Save::loadFile] PS4 BIN File Size: " << FF7SaveInfo::get()->fileSize(FF7SaveInfo::FORMAT::PS4BIN) << "\n"
84+
<< "[FF7Save::loadFile] PS4 BIN pfsSKKey IV: " << m_ps4_iv.toHex() << "\n"
85+
<< "[FF7Save::loadFile] PS4 BIN pfsSKKey KEY: " << m_ps4_key.toHex() << "\n";
86+
setFormat(FF7SaveInfo::FORMAT::PS4);
87+
}
88+
}
89+
}
6790
if ((file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSP)) && (file.peek(25)).startsWith(FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PSP)))
6891
return FF7SaveInfo::FORMAT::PSP;
6992
if ((file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::VGS)) && (file.peek(25)).startsWith(FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::VGS)))
@@ -934,7 +957,8 @@ char FF7Save::psx_block_type(int s)
934957
case FF7SaveInfo::FORMAT::PC:
935958
case FF7SaveInfo::FORMAT::SWITCH:
936959
case FF7SaveInfo::FORMAT::PSX:
937-
case FF7SaveInfo::FORMAT::PS3: return 0x00;
960+
case FF7SaveInfo::FORMAT::PS3:
961+
case FF7SaveInfo::FORMAT::PS4: return 0x00;
938962
case FF7SaveInfo::FORMAT::PGE: return _fileHeader.at(0);
939963
default:
940964
int index = 128 + (128 * s);
@@ -951,7 +975,8 @@ void FF7Save::setPsx_block_type(int s, char block_type)
951975
case FF7SaveInfo::FORMAT::PC:
952976
case FF7SaveInfo::FORMAT::SWITCH:
953977
case FF7SaveInfo::FORMAT::PSX:
954-
case FF7SaveInfo::FORMAT::PS3: return;
978+
case FF7SaveInfo::FORMAT::PS3:
979+
case FF7SaveInfo::FORMAT::PS4: return;
955980
case FF7SaveInfo::FORMAT::PGE: _fileHeader.replace(0, 1, QByteArray(1, block_type)); break;
956981
default:
957982
int index = 128 + (128 * s);
@@ -972,7 +997,8 @@ void FF7Save::setPsx_block_next(int s, int next)
972997
case FF7SaveInfo::FORMAT::PC:
973998
case FF7SaveInfo::FORMAT::SWITCH:
974999
case FF7SaveInfo::FORMAT::PSX:
975-
case FF7SaveInfo::FORMAT::PS3: return;
1000+
case FF7SaveInfo::FORMAT::PS3:
1001+
case FF7SaveInfo::FORMAT::PS4: return;
9761002
case FF7SaveInfo::FORMAT::PGE: _fileHeader.replace(8, 1, QByteArray(1, next)); break;
9771003
default:
9781004
int index = 128 + (128 * s);
@@ -989,7 +1015,8 @@ quint8 FF7Save::psx_block_next(int s)
9891015
case FF7SaveInfo::FORMAT::PC:
9901016
case FF7SaveInfo::FORMAT::SWITCH:
9911017
case FF7SaveInfo::FORMAT::PSX:
992-
case FF7SaveInfo::FORMAT::PS3: return 0x00;
1018+
case FF7SaveInfo::FORMAT::PS3:
1019+
case FF7SaveInfo::FORMAT::PS4: return 0x00;
9931020
case FF7SaveInfo::FORMAT::PGE: return quint8(_fileHeader.at(0x08));
9941021
default:
9951022
int index = 128 + (128 * s);
@@ -1006,7 +1033,8 @@ void FF7Save::setPsx_block_size(int s, int blockSize)
10061033
case FF7SaveInfo::FORMAT::PC:
10071034
case FF7SaveInfo::FORMAT::SWITCH:
10081035
case FF7SaveInfo::FORMAT::PSX:
1009-
case FF7SaveInfo::FORMAT::PS3: return;
1036+
case FF7SaveInfo::FORMAT::PS3:
1037+
case FF7SaveInfo::FORMAT::PS4: return;
10101038
default: break;
10111039
}
10121040

@@ -1029,6 +1057,7 @@ quint8 FF7Save::psx_block_size(int s)
10291057
switch (fileFormat) {
10301058
case FF7SaveInfo::FORMAT::UNKNOWN:
10311059
case FF7SaveInfo::FORMAT::PC:
1060+
case FF7SaveInfo::FORMAT::PS4:
10321061
case FF7SaveInfo::FORMAT::SWITCH: return 1;
10331062
case FF7SaveInfo::FORMAT::PSX: return quint8(QFile(fileName()).size() / FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSX));
10341063
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
@@ -1038,6 +1038,8 @@ class FF7TKDATA_EXPORT FF7Save: public QObject
10381038
bool fileHasChanged;
10391039
QString buffer_region; // hold the buffers region data.
10401040
QString SG_Region_String[15];
1041+
QByteArray m_ps4_iv;
1042+
QByteArray m_ps4_key;
10411043
QString filename;//opened file
10421044
QVector< SubContainer > parseXML(const QString &fileName, const QString &metadataPath, const QString &UserID);
10431045
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
*/
@@ -331,6 +359,28 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
331359
inline static const int PS_SIGNATURE_SIZE = 0x0014;
332360
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);
333361
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);
362+
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PS4 SAVE INFO~~~~~~~~~~~~~~~~~~~~~~~~~*/
363+
static const int PS4_FILE_SIZE = 0xA00000;
364+
static const int PS4_FILE_HEADER_SIZE = 0x00AF;
365+
inline static const QString PS4_FILE_DESCRIPTION = QT_TR_NOOP("PS4 Save File");
366+
inline static const QStringList PS4_VALID_EXTENSIONS { QStringLiteral("*.ff7") };
367+
inline static const QRegularExpression PS4_VALID_NAME_REGEX = QRegularExpression(QStringLiteral("save0[0-9].ff7"));
368+
inline static const QByteArray PS4_FILE_ID = QByteArray::fromRawData("\x17\x00\x00\x00\x00\x00\x00\x00", 8);
369+
inline static const QByteArray PS4_BINFILE_FILE_ID = QByteArray::fromRawData("\x70\x66\x73\x53\x4B\x4B\x65\x79", 8);
370+
static const int PS4_BINFILE_FILE_ID_SIZE = 8;
371+
static const int PS4_BINFILE_SIZE = 0x60;
372+
static const int PS4_BINFILE_IV_OFFSET= 0x10;
373+
static const int PS4_BINFILE_IV_SIZE= 0x10;
374+
static const int PS4_SEED_OFFSET = 0x0008;
375+
static const int PS4_SIGNATURE_OFFSET = 0x001C;
376+
static const int PS4_FILE_TYPE_OFFSET = 0x0038;
377+
static const int PS4_FILE_DISP_SIZE_OFFSET = 0x0040;
378+
static const int PS4_FILE_SIZE_OFFSET = 0x005C;
379+
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);
380+
/*~~~~~~~ PS4 Signing ~~~~~~~~~~~~~~*/
381+
static const int PS4_SIGNATURE_SIZE = 0x0014;
382+
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);
383+
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);
334384
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Mem Card Format~~~~~~~~~~~~~~~~~~~*/
335385
inline static const int VMC_FILE_SIZE = 0x20000;
336386
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
@@ -6915,6 +6915,10 @@ Die km / h beschleunigt berechnet werden während des Spielens </translation>
69156915
<source>XP AR GS Caetla SmartLink Dantel</source>
69166916
<translation type="unfinished">XP AR GS Caetla SmartLink Dantel</translation>
69176917
</message>
6918+
<message>
6919+
<source>PS4 Save File</source>
6920+
<translation type="unfinished">PS4 Spielstand</translation>
6921+
</message>
69186922
</context>
69196923
<context>
69206924
<name>ItemList</name>

translations/ff7tk_en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6915,6 +6915,10 @@ The km/h speeds are calculated while playing </translation>
69156915
<source>XP AR GS Caetla SmartLink Dantel</source>
69166916
<translation>XP AR GS Caetla SmartLink Dantel</translation>
69176917
</message>
6918+
<message>
6919+
<source>PS4 Save File</source>
6920+
<translation>PS4 Save File</translation>
6921+
</message>
69186922
</context>
69196923
<context>
69206924
<name>ItemList</name>

translations/ff7tk_es.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6915,6 +6915,10 @@ Los km/h son calculados mientras se juega </translation>
69156915
<source>XP AR GS Caetla SmartLink Dantel</source>
69166916
<translation type="unfinished">XP AR GS Caetla SmartLink Dantel</translation>
69176917
</message>
6918+
<message>
6919+
<source>PS4 Save File</source>
6920+
<translation type="unfinished">Partida Guardada PS4</translation>
6921+
</message>
69186922
</context>
69196923
<context>
69206924
<name>ItemList</name>

0 commit comments

Comments
 (0)