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 Feb 21, 2023
1 parent 10db20e commit 30d0933
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 10 deletions.
39 changes: 34 additions & 5 deletions src/data/FF7Save.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,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::instance()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()) == FF7SaveInfo::instance()->fileIdentifier(FF7SaveInfo::FORMAT::PS4)) {
QTextStream(stdout)
<< "[FF7Save::loadFile] PS4 Save "
<< file.peek(0x00B0+FF7SaveInfo::instance()->fileIdentifier(FF7SaveInfo::FORMAT::PS4).length()).mid(0x00B0,FF7SaveInfo::instance()->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::instance()->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::instance()->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 @@ -944,7 +967,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 @@ -961,7 +985,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 @@ -982,7 +1007,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 @@ -999,7 +1025,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 @@ -1016,7 +1043,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 @@ -1039,6 +1067,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 @@ -1043,6 +1043,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
31 changes: 26 additions & 5 deletions src/data/FF7SaveInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <QByteArrayList>
#include <QQmlEngine>


FF7SaveInfo *FF7SaveInfo::instance()
{
static FF7SaveInfo m;
Expand Down Expand Up @@ -51,6 +50,8 @@ int FF7SaveInfo::fileSize(FF7SaveInfo::FORMAT format)
case FORMAT::VMC: return instance()->d->VMC_FILE_SIZE;
case FORMAT::PSP: return instance()->d->PSP_FILE_SIZE;
case FORMAT::PS3: return instance()->d->PS3_FILE_SIZE;
case FORMAT::PS4: return instance()->d->PS4_FILE_SIZE;
case FORMAT::PS4BIN: return instance()->d->PS4_BINFILE_SIZE;
case FORMAT::DEX: return instance()->d->DEX_FILE_SIZE;
case FORMAT::VGS: return instance()->d->VGS_FILE_SIZE;
case FORMAT::SWITCH: return instance()->d->SWITCH_FILE_SIZE;
Expand All @@ -67,6 +68,8 @@ int FF7SaveInfo::fileHeaderSize(FF7SaveInfo::FORMAT format)
case FORMAT::VMC: return instance()->d->VMC_FILE_HEADER_SIZE;
case FORMAT::PSP: return instance()->d->PSP_FILE_HEADER_SIZE;
case FORMAT::PS3: return instance()->d->PS3_FILE_HEADER_SIZE;
case FORMAT::PS4: return instance()->d->PS4_FILE_HEADER_SIZE;
case FORMAT::PS4BIN: return instance()->d->PS4_BINFILE_FILE_ID_SIZE;
case FORMAT::DEX: return instance()->d->DEX_FILE_HEADER_SIZE;
case FORMAT::VGS: return instance()->d->VGS_FILE_HEADER_SIZE;
case FORMAT::SWITCH: return instance()->d->SWITCH_FILE_HEADER_SIZE;
Expand All @@ -83,6 +86,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 @@ -98,6 +102,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 @@ -112,7 +117,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 @@ -131,6 +137,8 @@ QByteArray FF7SaveInfo::fileIdentifier(FF7SaveInfo::FORMAT format)
case FORMAT::VMC: return instance()->d->VMC_FILE_ID;
case FORMAT::PSP: return instance()->d->PSP_FILE_ID;
case FORMAT::PS3: return instance()->d->PS3_FILE_ID;
case FORMAT::PS4: return instance()->d->PS4_FILE_ID;
case FORMAT::PS4BIN: return instance()->d->PS4_BINFILE_FILE_ID;
case FORMAT::DEX: return instance()->d->DEX_FILE_ID;
case FORMAT::VGS: return instance()->d->VGS_FILE_ID;
case FORMAT::SWITCH: return instance()->d->SWITCH_FILE_ID;
Expand All @@ -148,6 +156,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 instance()->d->PSP_FILE_HEADER;
case FORMAT::PS3: return instance()->d->PS3_FILE_HEADER;
case FORMAT::PS4: return instance()->d->PS4_FILE_HEADER;
default: return QByteArray();
}
}
Expand All @@ -161,6 +170,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(instance()->d->PSX_SLOT_HEADER.at(slot)).append(256, 0x00);
Expand All @@ -176,6 +186,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(instance()->d->PSX_SLOT_FOOTER_SIZE, 0x00);
Expand All @@ -188,6 +199,7 @@ QByteArray FF7SaveInfo::signingKey(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP:
case FORMAT::PS3: return instance()->d->PS_SIGNING_KEY;
case FORMAT::PS4: return instance()->d->PS4_SIGNING_KEY;
default: return QByteArray();
}
}
Expand All @@ -208,6 +220,7 @@ QByteArray FF7SaveInfo::signingIV(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP:
case FORMAT::PS3: return instance()->d->PS_SIGNING_IV;
case FORMAT::PS4: return instance()->d->PS4_SIGNING_IV;
default: return QByteArray();
}
}
Expand All @@ -217,6 +230,7 @@ int FF7SaveInfo::fileSeedOffset(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP: return instance()->d->PSP_SEED_OFFSET;
case FORMAT::PS3: return instance()->d->PS3_SEED_OFFSET;
case FORMAT::PS4: return instance()->d->PS4_SEED_OFFSET;
default: return -1;
}
}
Expand All @@ -226,6 +240,7 @@ int FF7SaveInfo::fileSignatureOffset(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP: return instance()->d->PSP_SIGNATURE_OFFSET;
case FORMAT::PS3: return instance()->d->PS3_SIGNATURE_OFFSET;
case FORMAT::PS4: return instance()->d->PS4_SIGNATURE_OFFSET;
default: return -1;
}
}
Expand All @@ -235,6 +250,7 @@ int FF7SaveInfo::fileSignatureSize(FF7SaveInfo::FORMAT format)
switch (format) {
case FORMAT::PSP:
case FORMAT::PS3: return instance()->d->PS_SIGNATURE_SIZE;
case FORMAT::PS4: return instance()->d->PS4_SIGNATURE_SIZE;
default: return 0;
}
}
Expand All @@ -251,6 +267,7 @@ QRegularExpression FF7SaveInfo::validNames(FF7SaveInfo::FORMAT format)
case FORMAT::PSX: return instance()->d->PSX_VALID_NAME_REGEX;
case FORMAT::PSP: return instance()->d->PSP_VALID_NAME_REGEX;
case FORMAT::PS3: return instance()->d->PS3_VALID_NAME_REGEX;
case FORMAT::PS4: return instance()->d->PS4_VALID_NAME_REGEX;
case FORMAT::DEX: return instance()->d->DEX_VALID_NAME_REGEX;
case FORMAT::VGS: return instance()->d->VGS_VALID_NAME_REGEX;
case FORMAT::VMC: return instance()->d->VMC_VALID_NAME_REGEX;
Expand All @@ -268,6 +285,7 @@ QString FF7SaveInfo::typeDescription(FF7SaveInfo::FORMAT format)
case FORMAT::PSX: return tr(instance()->d->PSX_FILE_DESCRIPTION.toUtf8());
case FORMAT::PSP: return tr(instance()->d->PSP_FILE_DESCRIPTION.toUtf8());
case FORMAT::PS3: return tr(instance()->d->PS3_FILE_DESCRIPTION.toUtf8());
case FORMAT::PS4: return tr(instance()->d->PS4_FILE_DESCRIPTION.toUtf8());
case FORMAT::DEX: return tr(instance()->d->DEX_FILE_DESCRIPTION.toUtf8());
case FORMAT::VGS: return tr(instance()->d->VGS_FILE_DESCRIPTION.toUtf8());
case FORMAT::VMC: return tr(instance()->d->VMC_FILE_DESCRIPTION.toUtf8());
Expand All @@ -285,6 +303,7 @@ QStringList FF7SaveInfo::typeExtension(FF7SaveInfo::FORMAT format)
case FORMAT::PSX: return instance()->d->PSX_VALID_EXTENSIONS;
case FORMAT::PSP: return instance()->d->PSP_VALID_EXTENSIONS;
case FORMAT::PS3: return instance()->d->PS3_VALID_EXTENSIONS;
case FORMAT::PS4: return instance()->d->PS4_VALID_EXTENSIONS;
case FORMAT::DEX: return instance()->d->DEX_VALID_EXTENSIONS;
case FORMAT::VGS: return instance()->d->VGS_VALID_EXTENSIONS;
case FORMAT::VMC: return instance()->d->VMC_VALID_EXTENSIONS;
Expand All @@ -305,25 +324,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(instance()->d->PC_VALID_EXTENSIONS.join(space)
, instance()->d->PSX_VALID_EXTENSIONS.join(space)
, instance()->d->PSP_VALID_EXTENSIONS.join(space)
, instance()->d->PS3_VALID_EXTENSIONS.join(space)
, instance()->d->PS4_VALID_EXTENSIONS.join(space)
, instance()->d->DEX_VALID_EXTENSIONS.join(space)
, instance()->d->VGS_VALID_EXTENSIONS.join(space)
, instance()->d->VMC_VALID_EXTENSIONS.join(space)
, instance()->d->SWITCH_VALID_EXTENSIONS.join(space)
, instance()->d->PGE_VALID_EXTENSIONS.join(space)
, instance()->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 @@ -336,6 +357,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 @@ -384,4 +406,3 @@ int FF7SaveInfo::psxSaveNameOffset(FF7SaveInfo::FORMAT format)
default: return -1;
}
}

50 changes: 50 additions & 0 deletions src/data/FF7SaveInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,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>
#include <ff7tkdata_export.h>
Expand Down Expand Up @@ -42,6 +53,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 @@ -69,6 +82,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.
* @sa qmlSingletonRegister()
Expand Down Expand Up @@ -330,6 +358,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 @@ -6876,6 +6876,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 @@ -6876,6 +6876,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 @@ -6876,6 +6876,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 30d0933

Please sign in to comment.