Skip to content

Commit

Permalink
Initial PS4 file support
Browse files Browse the repository at this point in the history
First phase PS4 compatibility
  • Loading branch information
vegetass4 authored and sithlord48 committed Nov 16, 2023
1 parent 4c44590 commit 5723f2b
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 9 deletions.
39 changes: 34 additions & 5 deletions src/data/FF7Save.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,29 @@ FF7SaveInfo::FORMAT FF7Save::fileDataFormat(QFile &file)
return FF7SaveInfo::FORMAT::UNKNOWN;
}
}
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)) {
QTextStream(stdout)
<< "[FF7Save::loadFile] PS4 Save "
<< file.peek(0x00B0+FF7SaveInfo::get()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).mid(0x00B0,FF7SaveInfo::get()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).toHex( )
<< "\n";
QFile ps4binfile(QFileInfo(file).path() + "/" + QFileInfo(file).fileName() + ".bin");//QFileInfo(file).baseName()
if (!ps4binfile.open(QIODevice::ReadOnly)) {
QTextStream(stdout) << "[FF7Save::loadFile] PS4 BIN File error: missing file: " << QFileInfo(ps4binfile).absoluteFilePath();
return FF7SaveInfo::FORMAT::UNKNOWN;
} else {
QTextStream(stdout) << "[FF7Save::loadFile] PS4 BIN File loaded: " << QFileInfo(ps4binfile).absoluteFilePath() << "\n";
if(ps4binfile.size() == FF7SaveInfo::get()->fileSize(FF7SaveInfo::FORMAT::PS4BIN) && (ps4binfile.peek(FF7SaveInfo::fileHeaderSize(FF7SaveInfo::FORMAT::PS4BIN)) == FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PS4BIN))) {
auto ps4bin = ps4binfile.readAll();
m_ps4_iv = ps4bin.mid(0x10, 0x10);
m_ps4_key = ps4bin.mid(0x20, 0x10);
QTextStream(stdout)
<< "[FF7Save::loadFile] PS4 BIN File Size: " << FF7SaveInfo::get()->fileSize(FF7SaveInfo::FORMAT::PS4BIN) << "\n"
<< "[FF7Save::loadFile] PS4 BIN pfsSKKey IV: " << m_ps4_iv.toHex() << "\n"
<< "[FF7Save::loadFile] PS4 BIN pfsSKKey KEY: " << m_ps4_key.toHex() << "\n";
setFormat(FF7SaveInfo::FORMAT::PS4);
}
}
}
if ((file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSP)) && (file.peek(25)).startsWith(FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::PSP)))
return FF7SaveInfo::FORMAT::PSP;
if ((file_size == FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::VGS)) && (file.peek(25)).startsWith(FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT::VGS)))
Expand Down Expand Up @@ -934,7 +957,8 @@ char FF7Save::psx_block_type(int s)
case FF7SaveInfo::FORMAT::PC:
case FF7SaveInfo::FORMAT::SWITCH:
case FF7SaveInfo::FORMAT::PSX:
case FF7SaveInfo::FORMAT::PS3: return 0x00;
case FF7SaveInfo::FORMAT::PS3:
case FF7SaveInfo::FORMAT::PS4: return 0x00;
case FF7SaveInfo::FORMAT::PGE: return _fileHeader.at(0);
default:
int index = 128 + (128 * s);
Expand All @@ -951,7 +975,8 @@ void FF7Save::setPsx_block_type(int s, char block_type)
case FF7SaveInfo::FORMAT::PC:
case FF7SaveInfo::FORMAT::SWITCH:
case FF7SaveInfo::FORMAT::PSX:
case FF7SaveInfo::FORMAT::PS3: return;
case FF7SaveInfo::FORMAT::PS3:
case FF7SaveInfo::FORMAT::PS4: return;
case FF7SaveInfo::FORMAT::PGE: _fileHeader.replace(0, 1, QByteArray(1, block_type)); break;
default:
int index = 128 + (128 * s);
Expand All @@ -972,7 +997,8 @@ void FF7Save::setPsx_block_next(int s, int next)
case FF7SaveInfo::FORMAT::PC:
case FF7SaveInfo::FORMAT::SWITCH:
case FF7SaveInfo::FORMAT::PSX:
case FF7SaveInfo::FORMAT::PS3: return;
case FF7SaveInfo::FORMAT::PS3:
case FF7SaveInfo::FORMAT::PS4: return;
case FF7SaveInfo::FORMAT::PGE: _fileHeader.replace(8, 1, QByteArray(1, next)); break;
default:
int index = 128 + (128 * s);
Expand All @@ -989,7 +1015,8 @@ quint8 FF7Save::psx_block_next(int s)
case FF7SaveInfo::FORMAT::PC:
case FF7SaveInfo::FORMAT::SWITCH:
case FF7SaveInfo::FORMAT::PSX:
case FF7SaveInfo::FORMAT::PS3: return 0x00;
case FF7SaveInfo::FORMAT::PS3:
case FF7SaveInfo::FORMAT::PS4: return 0x00;
case FF7SaveInfo::FORMAT::PGE: return quint8(_fileHeader.at(0x08));
default:
int index = 128 + (128 * s);
Expand All @@ -1006,7 +1033,8 @@ void FF7Save::setPsx_block_size(int s, int blockSize)
case FF7SaveInfo::FORMAT::PC:
case FF7SaveInfo::FORMAT::SWITCH:
case FF7SaveInfo::FORMAT::PSX:
case FF7SaveInfo::FORMAT::PS3: return;
case FF7SaveInfo::FORMAT::PS3:
case FF7SaveInfo::FORMAT::PS4: return;
default: break;
}

Expand All @@ -1029,6 +1057,7 @@ quint8 FF7Save::psx_block_size(int s)
switch (fileFormat) {
case FF7SaveInfo::FORMAT::UNKNOWN:
case FF7SaveInfo::FORMAT::PC:
case FF7SaveInfo::FORMAT::PS4:
case FF7SaveInfo::FORMAT::SWITCH: return 1;
case FF7SaveInfo::FORMAT::PSX: return quint8(QFile(fileName()).size() / FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSX));
case FF7SaveInfo::FORMAT::PS3: return quint8((QFile(fileName()).size() - 0x84) / FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT::PSX));
Expand Down
2 changes: 2 additions & 0 deletions src/data/FF7Save.h
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,8 @@ class FF7TKDATA_EXPORT FF7Save: public QObject
bool fileHasChanged;
QString buffer_region; // hold the buffers region data.
QString SG_Region_String[15];
QByteArray m_ps4_iv;
QByteArray m_ps4_key;
QString filename;//opened file
QVector< SubContainer > parseXML(const QString &fileName, const QString &metadataPath, const QString &UserID);
QVector< SubContainer > createMetadata(const QString &fileName, const QString &UserID);
Expand Down
30 changes: 26 additions & 4 deletions src/data/FF7SaveInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ int FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT format)
case FORMAT::VMC: return get()->d->VMC_FILE_SIZE;
case FORMAT::PSP: return get()->d->PSP_FILE_SIZE;
case FORMAT::PS3: return get()->d->PS3_FILE_SIZE;
case FORMAT::PS4: return get()->d->PS4_FILE_SIZE;
case FORMAT::PS4BIN: return get()->d->PS4_BINFILE_SIZE;
case FORMAT::DEX: return get()->d->DEX_FILE_SIZE;
case FORMAT::VGS: return get()->d->VGS_FILE_SIZE;
case FORMAT::SWITCH: return get()->d->SWITCH_FILE_SIZE;
Expand All @@ -46,6 +48,8 @@ int FF7SaveInfo::fileHeaderSize(FF7SaveInfo::FORMAT format)
case FORMAT::VMC: return get()->d->VMC_FILE_HEADER_SIZE;
case FORMAT::PSP: return get()->d->PSP_FILE_HEADER_SIZE;
case FORMAT::PS3: return get()->d->PS3_FILE_HEADER_SIZE;
case FORMAT::PS4: return get()->d->PS4_FILE_HEADER_SIZE;
case FORMAT::PS4BIN: return get()->d->PS4_BINFILE_FILE_ID_SIZE;
case FORMAT::DEX: return get()->d->DEX_FILE_HEADER_SIZE;
case FORMAT::VGS: return get()->d->VGS_FILE_HEADER_SIZE;
case FORMAT::SWITCH: return get()->d->SWITCH_FILE_HEADER_SIZE;
Expand All @@ -62,6 +66,7 @@ int FF7SaveInfo::slotHeaderSize(FF7SaveInfo::FORMAT format)
case FORMAT::VMC:
case FORMAT::PSP:
case FORMAT::PS3:
case FORMAT::PS4:
case FORMAT::DEX:
case FORMAT::PGE:
case FORMAT::PDA:
Expand All @@ -77,6 +82,7 @@ int FF7SaveInfo::slotFooterSize(FF7SaveInfo::FORMAT format)
case FORMAT::VMC:
case FORMAT::PSP:
case FORMAT::PS3:
case FORMAT::PS4:
case FORMAT::DEX:
case FORMAT::PGE:
case FORMAT::PDA:
Expand All @@ -91,7 +97,8 @@ int FF7SaveInfo::slotCount(FF7SaveInfo::FORMAT format)
case FORMAT::PDA:
case FORMAT::PGE:
case FORMAT::PSX:
case FORMAT::PS3: return 1;
case FORMAT::PS3:
case FORMAT::PS4: return 1;
case FORMAT::VMC:
case FORMAT::PSP:
case FORMAT::DEX:
Expand All @@ -110,6 +117,8 @@ QByteArray FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT format)
case FORMAT::VMC: return get()->d->VMC_FILE_ID;
case FORMAT::PSP: return get()->d->PSP_FILE_ID;
case FORMAT::PS3: return get()->d->PS3_FILE_ID;
case FORMAT::PS4: return get()->d->PS4_FILE_ID;
case FORMAT::PS4BIN: return get()->d->PS4_BINFILE_FILE_ID;
case FORMAT::DEX: return get()->d->DEX_FILE_ID;
case FORMAT::VGS: return get()->d->VGS_FILE_ID;
case FORMAT::SWITCH: return get()->d->SWITCH_FILE_ID;
Expand All @@ -127,6 +136,7 @@ QByteArray FF7SaveInfo::fileHeader(FF7SaveInfo::FORMAT format)
case FORMAT::VMC: return QByteArray(fileIdentifier(format)).append(fileHeaderSize(format) - fileIdentifier(format).length(), 0x00);
case FORMAT::PSP: return get()->d->PSP_FILE_HEADER;
case FORMAT::PS3: return get()->d->PS3_FILE_HEADER;
case FORMAT::PS4: return get()->d->PS4_FILE_HEADER;
default: return QByteArray();
}
}
Expand All @@ -140,6 +150,7 @@ QByteArray FF7SaveInfo::slotHeader(FF7SaveInfo::FORMAT format, int slot)
case FORMAT::PSX:
case FORMAT::PSP:
case FORMAT::PS3:
case FORMAT::PS4:
case FORMAT::DEX:
case FORMAT::VGS:
case FORMAT::VMC: return QByteArray(get()->d->PSX_SLOT_HEADER.at(slot)).append(256, 0x00);
Expand All @@ -155,6 +166,7 @@ QByteArray FF7SaveInfo::slotFooter(FF7SaveInfo::FORMAT format)
case FORMAT::PSX:
case FORMAT::PSP:
case FORMAT::PS3:
case FORMAT::PS4:
case FORMAT::DEX:
case FORMAT::VGS:
case FORMAT::VMC: return QByteArray(get()->d->PSX_SLOT_FOOTER_SIZE, 0x00);
Expand All @@ -167,6 +179,7 @@ QByteArray FF7SaveInfo::signingKey(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP:
case FORMAT::PS3: return get()->d->PS_SIGNING_KEY;
case FORMAT::PS4: return get()->d->PS4_SIGNING_KEY;
default: return QByteArray();
}
}
Expand All @@ -187,6 +200,7 @@ QByteArray FF7SaveInfo::signingIV(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP:
case FORMAT::PS3: return get()->d->PS_SIGNING_IV;
case FORMAT::PS4: return get()->d->PS4_SIGNING_IV;
default: return QByteArray();
}
}
Expand All @@ -196,6 +210,7 @@ int FF7SaveInfo::fileSeedOffset(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP: return get()->d->PSP_SEED_OFFSET;
case FORMAT::PS3: return get()->d->PS3_SEED_OFFSET;
case FORMAT::PS4: return get()->d->PS4_SEED_OFFSET;
default: return -1;
}
}
Expand All @@ -205,6 +220,7 @@ int FF7SaveInfo::fileSignatureOffset(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP: return get()->d->PSP_SIGNATURE_OFFSET;
case FORMAT::PS3: return get()->d->PS3_SIGNATURE_OFFSET;
case FORMAT::PS4: return get()->d->PS4_SIGNATURE_OFFSET;
default: return -1;
}
}
Expand All @@ -214,6 +230,7 @@ int FF7SaveInfo::fileSignatureSize(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP:
case FORMAT::PS3: return get()->d->PS_SIGNATURE_SIZE;
case FORMAT::PS4: return get()->d->PS4_SIGNATURE_SIZE;
default: return 0;
}
}
Expand All @@ -230,6 +247,7 @@ QRegularExpression FF7SaveInfo::validNames(FF7SaveInfo::FORMAT format)
case FORMAT::PSX: return get()->d->PSX_VALID_NAME_REGEX;
case FORMAT::PSP: return get()->d->PSP_VALID_NAME_REGEX;
case FORMAT::PS3: return get()->d->PS3_VALID_NAME_REGEX;
case FORMAT::PS4: return get()->d->PS4_VALID_NAME_REGEX;
case FORMAT::DEX: return get()->d->DEX_VALID_NAME_REGEX;
case FORMAT::VGS: return get()->d->VGS_VALID_NAME_REGEX;
case FORMAT::VMC: return get()->d->VMC_VALID_NAME_REGEX;
Expand All @@ -247,6 +265,7 @@ QString FF7SaveInfo::typeDescription(FF7SaveInfo::FORMAT format)
case FORMAT::PSX: return tr(get()->d->PSX_FILE_DESCRIPTION.toUtf8());
case FORMAT::PSP: return tr(get()->d->PSP_FILE_DESCRIPTION.toUtf8());
case FORMAT::PS3: return tr(get()->d->PS3_FILE_DESCRIPTION.toUtf8());
case FORMAT::PS4: return tr(get()->d->PS4_FILE_DESCRIPTION.toUtf8());
case FORMAT::DEX: return tr(get()->d->DEX_FILE_DESCRIPTION.toUtf8());
case FORMAT::VGS: return tr(get()->d->VGS_FILE_DESCRIPTION.toUtf8());
case FORMAT::VMC: return tr(get()->d->VMC_FILE_DESCRIPTION.toUtf8());
Expand All @@ -264,6 +283,7 @@ QStringList FF7SaveInfo::typeExtension(FF7SaveInfo::FORMAT format)
case FORMAT::PSX: return get()->d->PSX_VALID_EXTENSIONS;
case FORMAT::PSP: return get()->d->PSP_VALID_EXTENSIONS;
case FORMAT::PS3: return get()->d->PS3_VALID_EXTENSIONS;
case FORMAT::PS4: return get()->d->PS4_VALID_EXTENSIONS;
case FORMAT::DEX: return get()->d->DEX_VALID_EXTENSIONS;
case FORMAT::VGS: return get()->d->VGS_VALID_EXTENSIONS;
case FORMAT::VMC: return get()->d->VMC_VALID_EXTENSIONS;
Expand All @@ -284,25 +304,27 @@ QString FF7SaveInfo::typeFilter(FF7SaveInfo::FORMAT format)
QString FF7SaveInfo::knownTypesFilter()
{
QString space = QStringLiteral(" ");
QString allTypes = QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10")
QString allTypes = QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11")
.arg(get()->d->PC_VALID_EXTENSIONS.join(space)
, get()->d->PSX_VALID_EXTENSIONS.join(space)
, get()->d->PSP_VALID_EXTENSIONS.join(space)
, get()->d->PS3_VALID_EXTENSIONS.join(space)
, get()->d->PS4_VALID_EXTENSIONS.join(space)
, get()->d->DEX_VALID_EXTENSIONS.join(space)
, get()->d->VGS_VALID_EXTENSIONS.join(space)
, get()->d->VMC_VALID_EXTENSIONS.join(space)
, get()->d->SWITCH_VALID_EXTENSIONS.join(space)
, get()->d->PGE_VALID_EXTENSIONS.join(space)
, get()->d->PDA_VALID_EXTENSIONS.join(space));

return QStringLiteral("%1;;%2;;%3;;%4;;%5;;%6;;%7;;%8;;%9;;%10;;%11;;%12")
return QStringLiteral("%1;;%2;;%3;;%4;;%5;;%6;;%7;;%8;;%9;;%10;;%11;;%12;;%13")
.arg(tr("Known FF7 Save Types (%1)").arg(allTypes)
, typeFilter(FORMAT::PC)
, typeFilter(FORMAT::SWITCH)
, typeFilter(FORMAT::VMC)
, typeFilter(FORMAT::PSX)
, typeFilter(FORMAT::PS3)
, typeFilter(FORMAT::PS4)
, typeFilter(FORMAT::PSP)
, typeFilter(FORMAT::DEX)
, typeFilter(FORMAT::VGS)
Expand All @@ -315,6 +337,7 @@ bool FF7SaveInfo::isTypePC(FF7SaveInfo::FORMAT format)
{
switch(format) {
case FORMAT::SWITCH:
case FORMAT::PS4:
case FORMAT::PC: return true;
default: return false;
};
Expand Down Expand Up @@ -368,4 +391,3 @@ QByteArray FF7SaveInfo::defaultSaveData()
{
return get()->d->DEFAULT_SAVE;
}

50 changes: 50 additions & 0 deletions src/data/FF7SaveInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@

#pragma once

#ifdef _MSC_VER
# define PACK(structure) \
__pragma(pack(push, 1)) \
structure \
__pragma(pack(pop))
#elif defined(__MINGW32__)
#define PACK(structure) structure __attribute__ ((gcc_struct, __packed__))
#else
#define PACK(structure) structure Q_PACKED
#endif

#include <QObject>
#include <QRegularExpression>
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
Expand Down Expand Up @@ -36,6 +47,8 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
SWITCH = 7, //!< Switch Format
PGE = 8, //!< Psx Game Edit Style Single Save
PDA = 9, //!< GS , Dantel Style Save
PS4 = 10, //!< PS4 Save Format
PS4BIN = 11 //!< PS4 BIN File (pfsSKKey)
};
Q_ENUM(FORMAT)

Expand Down Expand Up @@ -63,6 +76,21 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
};
Q_ENUM(PSVINFO)

/**
* \struct pfsSKKey
* \brief Extra bin file (Sealedkey) used for PS4 format
*/
PACK(
struct pfsSKKey {
quint8 MAGIC[8]; /**< [0x0000] MAGIC (0x08) */
quint16 KEYSET; /**< [0x0008] KEYSET (0x02) */
quint8 pad[6]; /**< [0x000A] Padding zeros (0x06) */
quint8 IV[16]; /**< [0x0010] AES IV (0x10) */
quint8 KEY[32]; /**< [0x0020] AES KEY (0x20) */
quint8 SHA256[32]; /**< [0x0040] AES SHA256 (0x20) */
}
);

/**
* @brief Get the FF7SaveInfo Instance.
*/
Expand Down Expand Up @@ -331,6 +359,28 @@ class FF7TKDATA_EXPORT FF7SaveInfo : public QObject
inline static const int PS_SIGNATURE_SIZE = 0x0014;
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);
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);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PS4 SAVE INFO~~~~~~~~~~~~~~~~~~~~~~~~~*/
static const int PS4_FILE_SIZE = 0xA00000;
static const int PS4_FILE_HEADER_SIZE = 0x00AF;
inline static const QString PS4_FILE_DESCRIPTION = QT_TR_NOOP("PS4 Save File");
inline static const QStringList PS4_VALID_EXTENSIONS { QStringLiteral("*.ff7") };
inline static const QRegularExpression PS4_VALID_NAME_REGEX = QRegularExpression(QStringLiteral("save0[0-9].ff7"));
inline static const QByteArray PS4_FILE_ID = QByteArray::fromRawData("\x17\x00\x00\x00\x00\x00\x00\x00", 8);
inline static const QByteArray PS4_BINFILE_FILE_ID = QByteArray::fromRawData("\x70\x66\x73\x53\x4B\x4B\x65\x79", 8);
static const int PS4_BINFILE_FILE_ID_SIZE = 8;
static const int PS4_BINFILE_SIZE = 0x60;
static const int PS4_BINFILE_IV_OFFSET= 0x10;
static const int PS4_BINFILE_IV_SIZE= 0x10;
static const int PS4_SEED_OFFSET = 0x0008;
static const int PS4_SIGNATURE_OFFSET = 0x001C;
static const int PS4_FILE_TYPE_OFFSET = 0x0038;
static const int PS4_FILE_DISP_SIZE_OFFSET = 0x0040;
static const int PS4_FILE_SIZE_OFFSET = 0x005C;
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);
/*~~~~~~~ PS4 Signing ~~~~~~~~~~~~~~*/
static const int PS4_SIGNATURE_SIZE = 0x0014;
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);
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);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Mem Card Format~~~~~~~~~~~~~~~~~~~*/
inline static const int VMC_FILE_SIZE = 0x20000;
inline static const int VMC_FILE_HEADER_SIZE = 0x2000;
Expand Down
4 changes: 4 additions & 0 deletions translations/ff7tk_de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6915,6 +6915,10 @@ Die km / h beschleunigt berechnet werden während des Spielens </translation>
<source>XP AR GS Caetla SmartLink Dantel</source>
<translation type="unfinished">XP AR GS Caetla SmartLink Dantel</translation>
</message>
<message>
<source>PS4 Save File</source>
<translation type="unfinished">PS4 Spielstand</translation>
</message>
</context>
<context>
<name>ItemList</name>
Expand Down
4 changes: 4 additions & 0 deletions translations/ff7tk_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6915,6 +6915,10 @@ The km/h speeds are calculated while playing </translation>
<source>XP AR GS Caetla SmartLink Dantel</source>
<translation>XP AR GS Caetla SmartLink Dantel</translation>
</message>
<message>
<source>PS4 Save File</source>
<translation>PS4 Save File</translation>
</message>
</context>
<context>
<name>ItemList</name>
Expand Down
4 changes: 4 additions & 0 deletions translations/ff7tk_es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6915,6 +6915,10 @@ Los km/h son calculados mientras se juega </translation>
<source>XP AR GS Caetla SmartLink Dantel</source>
<translation type="unfinished">XP AR GS Caetla SmartLink Dantel</translation>
</message>
<message>
<source>PS4 Save File</source>
<translation type="unfinished">Partida Guardada PS4</translation>
</message>
</context>
<context>
<name>ItemList</name>
Expand Down
Loading

0 comments on commit 5723f2b

Please sign in to comment.