Skip to content

Commit a5f714d

Browse files
vegetass4sithlord48
authored andcommitted
Initial PS4 file support
First phase PS4 compatibility
1 parent cc9c88f commit a5f714d

File tree

12 files changed

+144
-10
lines changed

12 files changed

+144
-10
lines changed

src/data/FF7Save.cpp

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,29 @@ FF7SaveInfo::FORMAT FF7Save::fileDataFormat(QFile &file)
7676
return FF7SaveInfo::FORMAT::UNKNOWN;
7777
}
7878
}
79+
if ( (file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PS4)) && file.peek(0x00B0 + FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).mid(0x00B0,FF7SaveInfo::instance()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()) == FF7SaveInfo::instance()->fileIdentifier(FF7SaveInfo::FORMAT::PS4)) {
80+
QTextStream(stdout)
81+
<< "[FF7Save::loadFile] PS4 Save "
82+
<< file.peek(0x00B0+FF7SaveInfo::instance()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).mid(0x00B0,FF7SaveInfo::instance()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).toHex( )
83+
<< "\n";
84+
QFile ps4binfile(QFileInfo(file).path() + "/" + QFileInfo(file).fileName() + ".bin");//QFileInfo(file).baseName()
85+
if (!ps4binfile.open(QIODevice::ReadOnly)) {
86+
QTextStream(stdout) << "[FF7Save::loadFile] PS4 BIN File error: missing file: " << QFileInfo(ps4binfile).absoluteFilePath();
87+
return FF7SaveInfo::FORMAT::UNKNOWN;
88+
} else {
89+
QTextStream(stdout) << "[FF7Save::loadFile] PS4 BIN File loaded: " << QFileInfo(ps4binfile).absoluteFilePath() << "\n";
90+
if(ps4binfile.size() == FF7SaveInfo::instance()->fileSize(FF7SaveInfo::FORMAT::PS4BIN) && (ps4binfile.peek(FF7SaveInfo::fileHeaderSize(FF7SaveInfo::FORMAT::PS4BIN)) == FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PS4BIN))) {
91+
auto ps4bin = ps4binfile.readAll();
92+
m_ps4_iv = ps4bin.mid(0x10, 0x10);
93+
m_ps4_key = ps4bin.mid(0x20, 0x10);
94+
QTextStream(stdout)
95+
<< "[FF7Save::loadFile] PS4 BIN File Size: " << FF7SaveInfo::instance()->fileSize(FF7SaveInfo::FORMAT::PS4BIN) << "\n"
96+
<< "[FF7Save::loadFile] PS4 BIN pfsSKKey IV: " << m_ps4_iv.toHex() << "\n"
97+
<< "[FF7Save::loadFile] PS4 BIN pfsSKKey KEY: " << m_ps4_key.toHex() << "\n";
98+
setFormat(FF7SaveInfo::FORMAT::PS4);
99+
}
100+
}
101+
}
79102
if ((file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSP)) && (file.peek(25)).startsWith(FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PSP)))
80103
return FF7SaveInfo::FORMAT::PSP;
81104
if ((file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::VGS)) && (file.peek(25)).startsWith(FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::VGS)))
@@ -944,7 +967,8 @@ char FF7Save::psx_block_type(int s)
944967
case FF7SaveInfo::FORMAT::PC:
945968
case FF7SaveInfo::FORMAT::SWITCH:
946969
case FF7SaveInfo::FORMAT::PSX:
947-
case FF7SaveInfo::FORMAT::PS3: return 0x00;
970+
case FF7SaveInfo::FORMAT::PS3:
971+
case FF7SaveInfo::FORMAT::PS4: return 0x00;
948972
case FF7SaveInfo::FORMAT::PGE: return _fileHeader.at(0);
949973
default:
950974
int index = 128 + (128 * s);
@@ -961,7 +985,8 @@ void FF7Save::setPsx_block_type(int s, char block_type)
961985
case FF7SaveInfo::FORMAT::PC:
962986
case FF7SaveInfo::FORMAT::SWITCH:
963987
case FF7SaveInfo::FORMAT::PSX:
964-
case FF7SaveInfo::FORMAT::PS3: return;
988+
case FF7SaveInfo::FORMAT::PS3:
989+
case FF7SaveInfo::FORMAT::PS4: return;
965990
case FF7SaveInfo::FORMAT::PGE: _fileHeader.replace(0, 1, QByteArray(1, block_type)); break;
966991
default:
967992
int index = 128 + (128 * s);
@@ -982,7 +1007,8 @@ void FF7Save::setPsx_block_next(int s, int next)
9821007
case FF7SaveInfo::FORMAT::PC:
9831008
case FF7SaveInfo::FORMAT::SWITCH:
9841009
case FF7SaveInfo::FORMAT::PSX:
985-
case FF7SaveInfo::FORMAT::PS3: return;
1010+
case FF7SaveInfo::FORMAT::PS3:
1011+
case FF7SaveInfo::FORMAT::PS4: return;
9861012
case FF7SaveInfo::FORMAT::PGE: _fileHeader.replace(8, 1, QByteArray(1, next)); break;
9871013
default:
9881014
int index = 128 + (128 * s);
@@ -999,7 +1025,8 @@ quint8 FF7Save::psx_block_next(int s)
9991025
case FF7SaveInfo::FORMAT::PC:
10001026
case FF7SaveInfo::FORMAT::SWITCH:
10011027
case FF7SaveInfo::FORMAT::PSX:
1002-
case FF7SaveInfo::FORMAT::PS3: return 0x00;
1028+
case FF7SaveInfo::FORMAT::PS3:
1029+
case FF7SaveInfo::FORMAT::PS4: return 0x00;
10031030
case FF7SaveInfo::FORMAT::PGE: return quint8(_fileHeader.at(0x08));
10041031
default:
10051032
int index = 128 + (128 * s);
@@ -1016,7 +1043,8 @@ void FF7Save::setPsx_block_size(int s, int blockSize)
10161043
case FF7SaveInfo::FORMAT::PC:
10171044
case FF7SaveInfo::FORMAT::SWITCH:
10181045
case FF7SaveInfo::FORMAT::PSX:
1019-
case FF7SaveInfo::FORMAT::PS3: return;
1046+
case FF7SaveInfo::FORMAT::PS3:
1047+
case FF7SaveInfo::FORMAT::PS4: return;
10201048
default: break;
10211049
}
10221050

@@ -1039,6 +1067,7 @@ quint8 FF7Save::psx_block_size(int s)
10391067
switch (fileFormat) {
10401068
case FF7SaveInfo::FORMAT::UNKNOWN:
10411069
case FF7SaveInfo::FORMAT::PC:
1070+
case FF7SaveInfo::FORMAT::PS4:
10421071
case FF7SaveInfo::FORMAT::SWITCH: return 1;
10431072
case FF7SaveInfo::FORMAT::PSX: return quint8(QFile(fileName()).size() / FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSX));
10441073
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
@@ -1043,6 +1043,8 @@ class FF7TKDATA_EXPORT FF7Save: public QObject
10431043
bool fileHasChanged;
10441044
QString buffer_region; // hold the buffers region data.
10451045
QString SG_Region_String[15];
1046+
QByteArray m_ps4_iv;
1047+
QByteArray m_ps4_key;
10461048
QString filename;//opened file
10471049
QVector< SubContainer > parseXML(const QString &fileName, const QString &metadataPath, const QString &UserID);
10481050
QVector< SubContainer > createMetadata(const QString &fileName, const QString &UserID);

src/data/FF7SaveInfo.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include <QByteArrayList>
1919
#include <QQmlEngine>
2020

21-
2221
FF7SaveInfo *FF7SaveInfo::instance()
2322
{
2423
static FF7SaveInfo m;
@@ -51,6 +50,8 @@ int FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT format)
5150
case FORMAT::VMC: return instance()->d->VMC_FILE_SIZE;
5251
case FORMAT::PSP: return instance()->d->PSP_FILE_SIZE;
5352
case FORMAT::PS3: return instance()->d->PS3_FILE_SIZE;
53+
case FORMAT::PS4: return instance()->d->PS4_FILE_SIZE;
54+
case FORMAT::PS4BIN: return instance()->d->PS4_BINFILE_SIZE;
5455
case FORMAT::DEX: return instance()->d->DEX_FILE_SIZE;
5556
case FORMAT::VGS: return instance()->d->VGS_FILE_SIZE;
5657
case FORMAT::SWITCH: return instance()->d->SWITCH_FILE_SIZE;
@@ -67,6 +68,8 @@ int FF7SaveInfo::fileHeaderSize(FF7SaveInfo::FORMAT format)
6768
case FORMAT::VMC: return instance()->d->VMC_FILE_HEADER_SIZE;
6869
case FORMAT::PSP: return instance()->d->PSP_FILE_HEADER_SIZE;
6970
case FORMAT::PS3: return instance()->d->PS3_FILE_HEADER_SIZE;
71+
case FORMAT::PS4: return instance()->d->PS4_FILE_HEADER_SIZE;
72+
case FORMAT::PS4BIN: return instance()->d->PS4_BINFILE_FILE_ID_SIZE;
7073
case FORMAT::DEX: return instance()->d->DEX_FILE_HEADER_SIZE;
7174
case FORMAT::VGS: return instance()->d->VGS_FILE_HEADER_SIZE;
7275
case FORMAT::SWITCH: return instance()->d->SWITCH_FILE_HEADER_SIZE;
@@ -83,6 +86,7 @@ int FF7SaveInfo::slotHeaderSize(FF7SaveInfo::FORMAT format)
8386
case FORMAT::VMC:
8487
case FORMAT::PSP:
8588
case FORMAT::PS3:
89+
case FORMAT::PS4:
8690
case FORMAT::DEX:
8791
case FORMAT::PGE:
8892
case FORMAT::PDA:
@@ -98,6 +102,7 @@ int FF7SaveInfo::slotFooterSize(FF7SaveInfo::FORMAT format)
98102
case FORMAT::VMC:
99103
case FORMAT::PSP:
100104
case FORMAT::PS3:
105+
case FORMAT::PS4:
101106
case FORMAT::DEX:
102107
case FORMAT::PGE:
103108
case FORMAT::PDA:
@@ -112,7 +117,8 @@ int FF7SaveInfo::slotCount(FF7SaveInfo::FORMAT format)
112117
case FORMAT::PDA:
113118
case FORMAT::PGE:
114119
case FORMAT::PSX:
115-
case FORMAT::PS3: return 1;
120+
case FORMAT::PS3:
121+
case FORMAT::PS4: return 1;
116122
case FORMAT::VMC:
117123
case FORMAT::PSP:
118124
case FORMAT::DEX:
@@ -131,6 +137,8 @@ QByteArray FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT format)
131137
case FORMAT::VMC: return instance()->d->VMC_FILE_ID;
132138
case FORMAT::PSP: return instance()->d->PSP_FILE_ID;
133139
case FORMAT::PS3: return instance()->d->PS3_FILE_ID;
140+
case FORMAT::PS4: return instance()->d->PS4_FILE_ID;
141+
case FORMAT::PS4BIN: return instance()->d->PS4_BINFILE_FILE_ID;
134142
case FORMAT::DEX: return instance()->d->DEX_FILE_ID;
135143
case FORMAT::VGS: return instance()->d->VGS_FILE_ID;
136144
case FORMAT::SWITCH: return instance()->d->SWITCH_FILE_ID;
@@ -148,6 +156,7 @@ QByteArray FF7SaveInfo::fileHeader(FF7SaveInfo::FORMAT format)
148156
case FORMAT::VMC: return QByteArray(fileIdentifier(format)).append(fileHeaderSize(format) - fileIdentifier(format).length(), 0x00);
149157
case FORMAT::PSP: return instance()->d->PSP_FILE_HEADER;
150158
case FORMAT::PS3: return instance()->d->PS3_FILE_HEADER;
159+
case FORMAT::PS4: return instance()->d->PS4_FILE_HEADER;
151160
default: return QByteArray();
152161
}
153162
}
@@ -161,6 +170,7 @@ QByteArray FF7SaveInfo::slotHeader(FF7SaveInfo::FORMAT format, int slot)
161170
case FORMAT::PSX:
162171
case FORMAT::PSP:
163172
case FORMAT::PS3:
173+
case FORMAT::PS4:
164174
case FORMAT::DEX:
165175
case FORMAT::VGS:
166176
case FORMAT::VMC: return QByteArray(instance()->d->PSX_SLOT_HEADER.at(slot)).append(256, 0x00);
@@ -176,6 +186,7 @@ QByteArray FF7SaveInfo::slotFooter(FF7SaveInfo::FORMAT format)
176186
case FORMAT::PSX:
177187
case FORMAT::PSP:
178188
case FORMAT::PS3:
189+
case FORMAT::PS4:
179190
case FORMAT::DEX:
180191
case FORMAT::VGS:
181192
case FORMAT::VMC: return QByteArray(instance()->d->PSX_SLOT_FOOTER_SIZE, 0x00);
@@ -188,6 +199,7 @@ QByteArray FF7SaveInfo::signingKey(FF7SaveInfo::FORMAT format)
188199
switch (format) {
189200
case FORMAT::PSP:
190201
case FORMAT::PS3: return instance()->d->PS_SIGNING_KEY;
202+
case FORMAT::PS4: return instance()->d->PS4_SIGNING_KEY;
191203
default: return QByteArray();
192204
}
193205
}
@@ -208,6 +220,7 @@ QByteArray FF7SaveInfo::signingIV(FF7SaveInfo::FORMAT format)
208220
switch (format) {
209221
case FORMAT::PSP:
210222
case FORMAT::PS3: return instance()->d->PS_SIGNING_IV;
223+
case FORMAT::PS4: return instance()->d->PS4_SIGNING_IV;
211224
default: return QByteArray();
212225
}
213226
}
@@ -217,6 +230,7 @@ int FF7SaveInfo::fileSeedOffset(FF7SaveInfo::FORMAT format)
217230
switch (format) {
218231
case FORMAT::PSP: return instance()->d->PSP_SEED_OFFSET;
219232
case FORMAT::PS3: return instance()->d->PS3_SEED_OFFSET;
233+
case FORMAT::PS4: return instance()->d->PS4_SEED_OFFSET;
220234
default: return -1;
221235
}
222236
}
@@ -226,6 +240,7 @@ int FF7SaveInfo::fileSignatureOffset(FF7SaveInfo::FORMAT format)
226240
switch (format) {
227241
case FORMAT::PSP: return instance()->d->PSP_SIGNATURE_OFFSET;
228242
case FORMAT::PS3: return instance()->d->PS3_SIGNATURE_OFFSET;
243+
case FORMAT::PS4: return instance()->d->PS4_SIGNATURE_OFFSET;
229244
default: return -1;
230245
}
231246
}
@@ -235,6 +250,7 @@ int FF7SaveInfo::fileSignatureSize(FF7SaveInfo::FORMAT format)
235250
switch (format) {
236251
case FORMAT::PSP:
237252
case FORMAT::PS3: return instance()->d->PS_SIGNATURE_SIZE;
253+
case FORMAT::PS4: return instance()->d->PS4_SIGNATURE_SIZE;
238254
default: return 0;
239255
}
240256
}
@@ -251,6 +267,7 @@ QRegularExpression FF7SaveInfo::validNames(FF7SaveInfo::FORMAT format)
251267
case FORMAT::PSX: return instance()->d->PSX_VALID_NAME_REGEX;
252268
case FORMAT::PSP: return instance()->d->PSP_VALID_NAME_REGEX;
253269
case FORMAT::PS3: return instance()->d->PS3_VALID_NAME_REGEX;
270+
case FORMAT::PS4: return instance()->d->PS4_VALID_NAME_REGEX;
254271
case FORMAT::DEX: return instance()->d->DEX_VALID_NAME_REGEX;
255272
case FORMAT::VGS: return instance()->d->VGS_VALID_NAME_REGEX;
256273
case FORMAT::VMC: return instance()->d->VMC_VALID_NAME_REGEX;
@@ -268,6 +285,7 @@ QString FF7SaveInfo::typeDescription(FF7SaveInfo::FORMAT format)
268285
case FORMAT::PSX: return tr(instance()->d->PSX_FILE_DESCRIPTION.toUtf8());
269286
case FORMAT::PSP: return tr(instance()->d->PSP_FILE_DESCRIPTION.toUtf8());
270287
case FORMAT::PS3: return tr(instance()->d->PS3_FILE_DESCRIPTION.toUtf8());
288+
case FORMAT::PS4: return tr(instance()->d->PS4_FILE_DESCRIPTION.toUtf8());
271289
case FORMAT::DEX: return tr(instance()->d->DEX_FILE_DESCRIPTION.toUtf8());
272290
case FORMAT::VGS: return tr(instance()->d->VGS_FILE_DESCRIPTION.toUtf8());
273291
case FORMAT::VMC: return tr(instance()->d->VMC_FILE_DESCRIPTION.toUtf8());
@@ -285,6 +303,7 @@ QStringList FF7SaveInfo::typeExtension(FF7SaveInfo::FORMAT format)
285303
case FORMAT::PSX: return instance()->d->PSX_VALID_EXTENSIONS;
286304
case FORMAT::PSP: return instance()->d->PSP_VALID_EXTENSIONS;
287305
case FORMAT::PS3: return instance()->d->PS3_VALID_EXTENSIONS;
306+
case FORMAT::PS4: return instance()->d->PS4_VALID_EXTENSIONS;
288307
case FORMAT::DEX: return instance()->d->DEX_VALID_EXTENSIONS;
289308
case FORMAT::VGS: return instance()->d->VGS_VALID_EXTENSIONS;
290309
case FORMAT::VMC: return instance()->d->VMC_VALID_EXTENSIONS;
@@ -305,25 +324,27 @@ QString FF7SaveInfo::typeFilter(FF7SaveInfo::FORMAT format)
305324
QString FF7SaveInfo::knownTypesFilter()
306325
{
307326
QString space = QStringLiteral(" ");
308-
QString allTypes = QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10")
327+
QString allTypes = QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11")
309328
.arg(instance()->d->PC_VALID_EXTENSIONS.join(space)
310329
, instance()->d->PSX_VALID_EXTENSIONS.join(space)
311330
, instance()->d->PSP_VALID_EXTENSIONS.join(space)
312331
, instance()->d->PS3_VALID_EXTENSIONS.join(space)
332+
, instance()->d->PS4_VALID_EXTENSIONS.join(space)
313333
, instance()->d->DEX_VALID_EXTENSIONS.join(space)
314334
, instance()->d->VGS_VALID_EXTENSIONS.join(space)
315335
, instance()->d->VMC_VALID_EXTENSIONS.join(space)
316336
, instance()->d->SWITCH_VALID_EXTENSIONS.join(space)
317337
, instance()->d->PGE_VALID_EXTENSIONS.join(space)
318338
, instance()->d->PDA_VALID_EXTENSIONS.join(space));
319339

320-
return QStringLiteral("%1;;%2;;%3;;%4;;%5;;%6;;%7;;%8;;%9;;%10;;%11;;%12")
340+
return QStringLiteral("%1;;%2;;%3;;%4;;%5;;%6;;%7;;%8;;%9;;%10;;%11;;%12;;%13")
321341
.arg(tr("Known FF7 Save Types (%1)").arg(allTypes)
322342
, typeFilter(FORMAT::PC)
323343
, typeFilter(FORMAT::SWITCH)
324344
, typeFilter(FORMAT::VMC)
325345
, typeFilter(FORMAT::PSX)
326346
, typeFilter(FORMAT::PS3)
347+
, typeFilter(FORMAT::PS4)
327348
, typeFilter(FORMAT::PSP)
328349
, typeFilter(FORMAT::DEX)
329350
, typeFilter(FORMAT::VGS)
@@ -336,6 +357,7 @@ bool FF7SaveInfo::isTypePC(FF7SaveInfo::FORMAT format)
336357
{
337358
switch(format) {
338359
case FORMAT::SWITCH:
360+
case FORMAT::PS4:
339361
case FORMAT::PC: return true;
340362
default: return false;
341363
};
@@ -384,4 +406,3 @@ int FF7SaveInfo::psxSaveNameOffset(FF7SaveInfo::FORMAT format)
384406
default: return -1;
385407
}
386408
}
387-

src/data/FF7SaveInfo.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@
1515
/****************************************************************************/
1616
#pragma once
1717

18+
#ifdef _MSC_VER
19+
# define PACK(structure) \
20+
__pragma(pack(push, 1)) \
21+
structure \
22+
__pragma(pack(pop))
23+
#elif defined(__MINGW32__)
24+
#define PACK(structure) structure __attribute__ ((gcc_struct, __packed__))
25+
#else
26+
#define PACK(structure) structure Q_PACKED
27+
#endif
28+
1829
#include <QObject>
1930
#include <QRegularExpression>
2031
#include <ff7tkdata_export.h>
@@ -42,6 +53,8 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
4253
SWITCH = 7, //!< Switch Format
4354
PGE = 8, //!< Psx Game Edit Style Single Save
4455
PDA = 9, //!< GS , Dantel Style Save
56+
PS4 = 10, //!< PS4 Save Format
57+
PS4BIN = 11 //!< PS4 BIN File (pfsSKKey)
4558
};
4659
Q_ENUM(FORMAT)
4760

@@ -69,6 +82,21 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
6982
};
7083
Q_ENUM(PSVINFO)
7184

85+
/**
86+
* \struct pfsSKKey
87+
* \brief Extra bin file (Sealedkey) used for PS4 format
88+
*/
89+
PACK(
90+
struct pfsSKKey {
91+
quint8 MAGIC[8]; /**< [0x0000] MAGIC (0x08) */
92+
quint16 KEYSET; /**< [0x0008] KEYSET (0x02) */
93+
quint8 pad[6]; /**< [0x000A] Padding zeros (0x06) */
94+
quint8 IV[16]; /**< [0x0010] AES IV (0x10) */
95+
quint8 KEY[32]; /**< [0x0020] AES KEY (0x20) */
96+
quint8 SHA256[32]; /**< [0x0040] AES SHA256 (0x20) */
97+
}
98+
);
99+
72100
/**
73101
* @brief Get the FF7SaveInfo Instance.
74102
* @sa qmlSingletonRegister()
@@ -330,6 +358,28 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
330358
inline static const int PS_SIGNATURE_SIZE = 0x0014;
331359
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);
332360
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);
361+
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PS4 SAVE INFO~~~~~~~~~~~~~~~~~~~~~~~~~*/
362+
static const int PS4_FILE_SIZE = 0xA00000;
363+
static const int PS4_FILE_HEADER_SIZE = 0x00AF;
364+
inline static const QString PS4_FILE_DESCRIPTION = QT_TR_NOOP("PS4 Save File");
365+
inline static const QStringList PS4_VALID_EXTENSIONS { QStringLiteral("*.ff7") };
366+
inline static const QRegularExpression PS4_VALID_NAME_REGEX = QRegularExpression(QStringLiteral("save0[0-9].ff7"));
367+
inline static const QByteArray PS4_FILE_ID = QByteArray::fromRawData("\x17\x00\x00\x00\x00\x00\x00\x00", 8);
368+
inline static const QByteArray PS4_BINFILE_FILE_ID = QByteArray::fromRawData("\x70\x66\x73\x53\x4B\x4B\x65\x79", 8);
369+
static const int PS4_BINFILE_FILE_ID_SIZE = 8;
370+
static const int PS4_BINFILE_SIZE = 0x60;
371+
static const int PS4_BINFILE_IV_OFFSET= 0x10;
372+
static const int PS4_BINFILE_IV_SIZE= 0x10;
373+
static const int PS4_SEED_OFFSET = 0x0008;
374+
static const int PS4_SIGNATURE_OFFSET = 0x001C;
375+
static const int PS4_FILE_TYPE_OFFSET = 0x0038;
376+
static const int PS4_FILE_DISP_SIZE_OFFSET = 0x0040;
377+
static const int PS4_FILE_SIZE_OFFSET = 0x005C;
378+
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);
379+
/*~~~~~~~ PS4 Signing ~~~~~~~~~~~~~~*/
380+
static const int PS4_SIGNATURE_SIZE = 0x0014;
381+
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);
382+
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);
333383
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Mem Card Format~~~~~~~~~~~~~~~~~~~*/
334384
inline static const int VMC_FILE_SIZE = 0x20000;
335385
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
@@ -6872,6 +6872,10 @@ Die km / h beschleunigt berechnet werden während des Spielens </translation>
68726872
<source>XP AR GS Caetla SmartLink Dantel</source>
68736873
<translation type="unfinished">XP AR GS Caetla SmartLink Dantel</translation>
68746874
</message>
6875+
<message>
6876+
<source>PS4 Save File</source>
6877+
<translation type="unfinished">PS4 Spielstand</translation>
6878+
</message>
68756879
</context>
68766880
<context>
68776881
<name>ItemList</name>

translations/ff7tk_en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6872,6 +6872,10 @@ The km/h speeds are calculated while playing </translation>
68726872
<source>XP AR GS Caetla SmartLink Dantel</source>
68736873
<translation>XP AR GS Caetla SmartLink Dantel</translation>
68746874
</message>
6875+
<message>
6876+
<source>PS4 Save File</source>
6877+
<translation>PS4 Save File</translation>
6878+
</message>
68756879
</context>
68766880
<context>
68776881
<name>ItemList</name>

translations/ff7tk_es.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6872,6 +6872,10 @@ Los km/h son calculados mientras se juega </translation>
68726872
<source>XP AR GS Caetla SmartLink Dantel</source>
68736873
<translation type="unfinished">XP AR GS Caetla SmartLink Dantel</translation>
68746874
</message>
6875+
<message>
6876+
<source>PS4 Save File</source>
6877+
<translation type="unfinished">Partida Guardada PS4</translation>
6878+
</message>
68756879
</context>
68766880
<context>
68776881
<name>ItemList</name>

0 commit comments

Comments
 (0)