improved RDR 2 support, libragephoto upstream
This commit is contained in:
		
							parent
							
								
									a10d259db1
								
							
						
					
					
						commit
						6e38894bcc
					
				
					 5 changed files with 43 additions and 85 deletions
				
			
		| 
						 | 
				
			
			@ -277,13 +277,13 @@ void ProfileInterface::directoryChanged(const QString &path)
 | 
			
		|||
 | 
			
		||||
    const QStringList files = dir.entryList(QDir::Files);
 | 
			
		||||
    for (const QString &fileName : files) {
 | 
			
		||||
        if (fileName.startsWith("SGTA5") && !fileName.endsWith(".bak")) {
 | 
			
		||||
        if ((fileName.startsWith("SGTA5") || fileName.startsWith("SRDR3")) && !fileName.endsWith(".bak")) {
 | 
			
		||||
            t_savegameFiles << fileName;
 | 
			
		||||
            if (!savegameFiles.contains(fileName)) {
 | 
			
		||||
                n_savegameFiles << fileName;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (fileName.startsWith("PGTA5") && !fileName.endsWith(".bak")) {
 | 
			
		||||
        if ((fileName.startsWith("PGTA5") || fileName.startsWith("PRDR3")) && !fileName.endsWith(".bak")) {
 | 
			
		||||
            t_snapmaticPics << fileName;
 | 
			
		||||
            if (fileName.endsWith(".hidden")) {
 | 
			
		||||
                const QString originalFileName = fileName.left(fileName.length() - 7);
 | 
			
		||||
| 
						 | 
				
			
			@ -559,18 +559,18 @@ fileDialogPreOpen: //Work?
 | 
			
		|||
    for (const QByteArray &imageFormat : QImageReader::supportedImageFormats()) {
 | 
			
		||||
        imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " ";
 | 
			
		||||
    }
 | 
			
		||||
    QString importableFormatsStr = QString("*.g5e SGTA* PGTA*");
 | 
			
		||||
    QString importableFormatsStr = QString("*.g5e SGTA5* PGTA5*");
 | 
			
		||||
    if (!imageFormatsStr.trimmed().isEmpty()) {
 | 
			
		||||
        importableFormatsStr = QString("*.g5e%1SGTA* PGTA*").arg(imageFormatsStr);
 | 
			
		||||
        importableFormatsStr = QString("*.g5e%1SGTA5* PGTA5*").arg(imageFormatsStr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QStringList filters;
 | 
			
		||||
    filters << tr("Importable files (%1)").arg(importableFormatsStr);
 | 
			
		||||
    filters << tr("GTA V Export (*.g5e)");
 | 
			
		||||
    filters << tr("Savegames files (SGTA*)");
 | 
			
		||||
    filters << tr("Snapmatic pictures (PGTA*)");
 | 
			
		||||
    filters << tr("All importable files (%1)").arg(importableFormatsStr);
 | 
			
		||||
    filters << tr("GTA V Export (%1)").arg("*.g5e");
 | 
			
		||||
    filters << tr("GTA V Savegames files (%1)").arg("SGTA5*");
 | 
			
		||||
    filters << tr("GTA V Snapmatic files (%1)").arg("PGTA5*");
 | 
			
		||||
    filters << tr("All image files (%1)").arg(imageFormatsStr.trimmed());
 | 
			
		||||
    filters << tr("All files (**)");
 | 
			
		||||
    filters << tr("All files (%1)").arg("**");
 | 
			
		||||
    fileDialog.setNameFilters(filters);
 | 
			
		||||
 | 
			
		||||
    QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls());
 | 
			
		||||
| 
						 | 
				
			
			@ -796,15 +796,8 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime
 | 
			
		|||
                        cEnough++;
 | 
			
		||||
                    }
 | 
			
		||||
                    spJson.createdDateTime = importDateTime;
 | 
			
		||||
#if QT_VERSION >= 0x060000
 | 
			
		||||
                    quint64 timestamp = spJson.createdDateTime.toSecsSinceEpoch();
 | 
			
		||||
                    if (timestamp > UINT32_MAX) {
 | 
			
		||||
                        timestamp = UINT32_MAX;
 | 
			
		||||
                    }
 | 
			
		||||
                    spJson.createdTimestamp = (quint32)timestamp;
 | 
			
		||||
#else
 | 
			
		||||
                    spJson.createdTimestamp = spJson.createdDateTime.toTime_t();
 | 
			
		||||
#endif
 | 
			
		||||
                    qint64 timestamp = spJson.createdDateTime.toSecsSinceEpoch();
 | 
			
		||||
                    spJson.createdTimestamp = timestamp;
 | 
			
		||||
                    picture->setSnapmaticProperties(spJson);
 | 
			
		||||
                    const QString picFileName = QString("PGTA5%1").arg(QString::number(spJson.uid));
 | 
			
		||||
                    picture->setPicFileName(picFileName);
 | 
			
		||||
| 
						 | 
				
			
			@ -854,15 +847,8 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime
 | 
			
		|||
                                cEnough++;
 | 
			
		||||
                            }
 | 
			
		||||
                            spJson.createdDateTime = importDateTime;
 | 
			
		||||
#if QT_VERSION >= 0x060000
 | 
			
		||||
                            quint64 timestamp = spJson.createdDateTime.toSecsSinceEpoch();
 | 
			
		||||
                            if (timestamp > UINT32_MAX) {
 | 
			
		||||
                                timestamp = UINT32_MAX;
 | 
			
		||||
                            }
 | 
			
		||||
                            spJson.createdTimestamp = (quint32)timestamp;
 | 
			
		||||
#else
 | 
			
		||||
                            spJson.createdTimestamp = spJson.createdDateTime.toTime_t();
 | 
			
		||||
#endif
 | 
			
		||||
                            qint64 timestamp = spJson.createdDateTime.toSecsSinceEpoch();
 | 
			
		||||
                            spJson.createdTimestamp = timestamp;
 | 
			
		||||
                            picture->setSnapmaticProperties(spJson);
 | 
			
		||||
                            const QString picFileName = QString("PGTA5%1").arg(QString::number(spJson.uid));
 | 
			
		||||
                            picture->setPicFileName(picFileName);
 | 
			
		||||
| 
						 | 
				
			
			@ -1124,15 +1110,15 @@ bool ProfileInterface::importSnapmaticPicture(SnapmaticPicture *picture, bool wa
 | 
			
		|||
{
 | 
			
		||||
    QString picFileName = picture->getPictureFileName();
 | 
			
		||||
    QString adjustedFileName = picture->getOriginalPictureFileName();
 | 
			
		||||
    if (!picFileName.startsWith("PGTA5")) {
 | 
			
		||||
    if (!picFileName.startsWith("PGTA5") && !picFileName.startsWith("PRDR3")) {
 | 
			
		||||
        if (warn)
 | 
			
		||||
            QMessageBox::warning(this, tr("Import..."), tr("Failed to import the Snapmatic picture, file not begin with PGTA or end with .g5e"));
 | 
			
		||||
            QMessageBox::warning(this, tr("Import..."), tr("Photo import failed! It is not a GTA V or RDR 2 compatible photo"));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    else if (QFile::exists(profileFolder % "/" % adjustedFileName) || QFile::exists(profileFolder % "/" % adjustedFileName % ".hidden")) {
 | 
			
		||||
        SnapmaticProperties snapmaticProperties = picture->getSnapmaticProperties();
 | 
			
		||||
        if (warn) {
 | 
			
		||||
            int uchoice = QMessageBox::question(this, tr("Import..."), tr("A Snapmatic picture already exists with the uid %1, you want assign your import a new uid and timestamp?").arg(QString::number(snapmaticProperties.uid)), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
 | 
			
		||||
            int uchoice = QMessageBox::question(this, tr("Import..."), tr("A Photo already exists with the uid %1, you want assign your import a new uid and timestamp?").arg(QString::number(snapmaticProperties.uid)), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
 | 
			
		||||
            if (uchoice == QMessageBox::Yes) {
 | 
			
		||||
                // Update Snapmatic uid
 | 
			
		||||
                snapmaticProperties.uid = getRandomUid();
 | 
			
		||||
| 
						 | 
				
			
			@ -1177,15 +1163,8 @@ bool ProfileInterface::importSnapmaticPicture(SnapmaticPicture *picture, bool wa
 | 
			
		|||
            // Update Snapmatic uid
 | 
			
		||||
            snapmaticProperties.uid = getRandomUid();
 | 
			
		||||
            snapmaticProperties.createdDateTime = QDateTime::currentDateTime();
 | 
			
		||||
#if QT_VERSION >= 0x060000
 | 
			
		||||
            quint64 timestamp = snapmaticProperties.createdDateTime.toSecsSinceEpoch();
 | 
			
		||||
            if (timestamp > UINT32_MAX) {
 | 
			
		||||
                timestamp = UINT32_MAX;
 | 
			
		||||
            }
 | 
			
		||||
            snapmaticProperties.createdTimestamp = (quint32)timestamp;
 | 
			
		||||
#else
 | 
			
		||||
            snapmaticProperties.createdTimestamp = snapmaticProperties.createdDateTime.toTime_t();
 | 
			
		||||
#endif
 | 
			
		||||
            qint64 timestamp = snapmaticProperties.createdDateTime.toSecsSinceEpoch();
 | 
			
		||||
            snapmaticProperties.createdTimestamp = timestamp;
 | 
			
		||||
            bool fExists = QFile::exists(profileFolder % "/PGTA5" % QString::number(snapmaticProperties.uid));
 | 
			
		||||
            bool fExistsBackup = QFile::exists(profileFolder % "/PGTA5" % QString::number(snapmaticProperties.uid) % ".bak");
 | 
			
		||||
            bool fExistsHidden = QFile::exists(profileFolder % "/PGTA5" % QString::number(snapmaticProperties.uid) % ".hidden");
 | 
			
		||||
| 
						 | 
				
			
			@ -1219,7 +1198,7 @@ bool ProfileInterface::importSnapmaticPicture(SnapmaticPicture *picture, bool wa
 | 
			
		|||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        if (warn)
 | 
			
		||||
            QMessageBox::warning(this, tr("Import..."), tr("Failed to import the Snapmatic picture, can't copy the file into profile"));
 | 
			
		||||
            QMessageBox::warning(this, tr("Import..."), tr("Photo import failed! Can not copy the file in the profile"));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1255,13 +1234,13 @@ bool ProfileInterface::importSavegameData(SavegameData *savegame, QString sgdPat
 | 
			
		|||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            if (warn)
 | 
			
		||||
                QMessageBox::warning(this, tr("Import..."), tr("Failed to import the Savegame, can't copy the file into profile"));
 | 
			
		||||
                QMessageBox::warning(this, tr("Import..."), tr("Savegame import failed! Can not copy the file in the profile"));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        if (warn)
 | 
			
		||||
            QMessageBox::warning(this, tr("Import..."), tr("Failed to import the Savegame, no Savegame slot is left"));
 | 
			
		||||
            QMessageBox::warning(this, tr("Import..."), tr("Savegame import failed! No Savegame slot is available"));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,40 +45,18 @@ void ProfileLoader::run()
 | 
			
		|||
    QVector<QString> savegameFiles;
 | 
			
		||||
    QVector<QString> snapmaticPics;
 | 
			
		||||
 | 
			
		||||
#ifdef Q_OS_WIN
 | 
			
		||||
    QDir dir(profileFolder);
 | 
			
		||||
    const QStringList files = dir.entryList(QDir::Files);
 | 
			
		||||
    for (const QString &fileName : files) {
 | 
			
		||||
        if (fileName.startsWith("SGTA5") && !fileName.endsWith(".bak")) {
 | 
			
		||||
        if ((fileName.startsWith("SGTA5") || fileName.startsWith("SRDR3")) && !fileName.endsWith(".bak")) {
 | 
			
		||||
            savegameFiles << fileName;
 | 
			
		||||
            maximumV++;
 | 
			
		||||
        }
 | 
			
		||||
        if (fileName.startsWith("PGTA5") && !fileName.endsWith(".bak")) {
 | 
			
		||||
        if ((fileName.startsWith("PGTA5") || fileName.startsWith("PRDR3")) && !fileName.endsWith(".bak")) {
 | 
			
		||||
            snapmaticPics << fileName;
 | 
			
		||||
            maximumV++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    DIR *dirp = opendir(profileFolder.toUtf8().constData());
 | 
			
		||||
    struct dirent *dp;
 | 
			
		||||
    while ((dp = readdir(dirp)) != 0) {
 | 
			
		||||
        const QString fileName = QString::fromUtf8(dp->d_name);
 | 
			
		||||
        const QString filePath = profileFolder % "/" % fileName;
 | 
			
		||||
        struct stat fileStat;
 | 
			
		||||
        stat(filePath.toUtf8().constData(), &fileStat);
 | 
			
		||||
        if (S_ISREG(fileStat.st_mode) != 0) {
 | 
			
		||||
            if (fileName.startsWith("SGTA5") && !fileName.endsWith(".bak")) {
 | 
			
		||||
                savegameFiles << fileName;
 | 
			
		||||
                maximumV++;
 | 
			
		||||
            }
 | 
			
		||||
            if (fileName.startsWith("PGTA5") && !fileName.endsWith(".bak")) {
 | 
			
		||||
                snapmaticPics << fileName;
 | 
			
		||||
                maximumV++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    closedir(dirp);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // Directory successfully scanned
 | 
			
		||||
    emit directoryScanned(savegameFiles, snapmaticPics);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*****************************************************************************
 | 
			
		||||
* gta5view Grand Theft Auto V Profile Viewer
 | 
			
		||||
* Copyright (C) 2016-2017 Syping
 | 
			
		||||
* Copyright (C) 2016-2023 Syping
 | 
			
		||||
*
 | 
			
		||||
* This program is free software: you can redistribute it and/or modify
 | 
			
		||||
* it under the terms of the GNU General Public License as published by
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +24,8 @@
 | 
			
		|||
#include <QFile>
 | 
			
		||||
 | 
			
		||||
#define savegameHeaderLength 260
 | 
			
		||||
#define verificationValue QByteArray::fromHex("00000001")
 | 
			
		||||
#define verificationValue_GTA5 QByteArray::fromHex("00000001")
 | 
			
		||||
#define verificationValue_RDR2 QByteArray::fromHex("00000004")
 | 
			
		||||
 | 
			
		||||
SavegameData::SavegameData(const QString &fileName, QObject *parent) : QObject(parent), savegameFileName(fileName)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -57,13 +58,10 @@ bool SavegameData::readingSavegame()
 | 
			
		|||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    QByteArray savegameHeaderLine = saveFile->read(savegameHeaderLength);
 | 
			
		||||
    if (savegameHeaderLine.left(4) == verificationValue)
 | 
			
		||||
    {
 | 
			
		||||
    if (savegameHeaderLine.startsWith(verificationValue_GTA5) || savegameHeaderLine.startsWith(verificationValue_RDR2)) {
 | 
			
		||||
        savegameStr = getSavegameDataString(savegameHeaderLine);
 | 
			
		||||
        if (savegameStr.length() >= 1)
 | 
			
		||||
        {
 | 
			
		||||
            savegameOk = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    saveFile->close();
 | 
			
		||||
    saveFile->deleteLater();
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +72,12 @@ bool SavegameData::readingSavegame()
 | 
			
		|||
QString SavegameData::getSavegameDataString(const QByteArray &savegameHeader)
 | 
			
		||||
{
 | 
			
		||||
    QByteArray savegameBytes = savegameHeader.left(savegameHeaderLength);
 | 
			
		||||
    QList<QByteArray> savegameBytesList = savegameBytes.split(char(0x01));
 | 
			
		||||
    char split_byte = 0x00;
 | 
			
		||||
    if (savegameHeader.startsWith(verificationValue_GTA5))
 | 
			
		||||
        split_byte = 0x01;
 | 
			
		||||
    else if (savegameHeader.startsWith(verificationValue_RDR2))
 | 
			
		||||
        split_byte = 0x04;
 | 
			
		||||
    QList<QByteArray> savegameBytesList = savegameBytes.split(split_byte);
 | 
			
		||||
    savegameBytes = savegameBytesList.at(1);
 | 
			
		||||
    savegameBytesList.clear();
 | 
			
		||||
    return SnapmaticPicture::parseTitleString(savegameBytes);
 | 
			
		||||
| 
						 | 
				
			
			@ -82,15 +85,12 @@ QString SavegameData::getSavegameDataString(const QByteArray &savegameHeader)
 | 
			
		|||
 | 
			
		||||
bool SavegameData::readingSavegameFromFile(const QString &fileName)
 | 
			
		||||
{
 | 
			
		||||
    if (fileName != "")
 | 
			
		||||
    {
 | 
			
		||||
    if (fileName != "") {
 | 
			
		||||
        savegameFileName = fileName;
 | 
			
		||||
        return readingSavegame();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SavegameData::isSavegameOk()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -564,11 +564,12 @@ fileDialogPreOpen:
 | 
			
		|||
    fileDialog.setWindowTitle(tr("Open File..."));
 | 
			
		||||
 | 
			
		||||
    QStringList filters;
 | 
			
		||||
    filters << ProfileInterface::tr("All profile files (*.g5e SGTA* PGTA*)");
 | 
			
		||||
    filters << ProfileInterface::tr("GTA V Export (*.g5e)");
 | 
			
		||||
    filters << ProfileInterface::tr("Savegames files (SGTA*)");
 | 
			
		||||
    filters << ProfileInterface::tr("Snapmatic pictures (PGTA*)");
 | 
			
		||||
    filters << ProfileInterface::tr("All files (**)");
 | 
			
		||||
    filters << ProfileInterface::tr("All profile files (%1)").arg("*.g5e SGTA5* PGTA5* PRDR3*");
 | 
			
		||||
    filters << ProfileInterface::tr("GTA V Export (%1)").arg("*.g5e");
 | 
			
		||||
    filters << ProfileInterface::tr("GTA V Savegames files (%1)").arg("SGTA5*");
 | 
			
		||||
    filters << ProfileInterface::tr("GTA V Snapmatic files (%1)").arg("PGTA5*");
 | 
			
		||||
    filters << ProfileInterface::tr("RDR 2 Photo files (%1)").arg("PRDR3*");
 | 
			
		||||
    filters << ProfileInterface::tr("All files (%1)").arg("**");
 | 
			
		||||
    fileDialog.setNameFilters(filters);
 | 
			
		||||
 | 
			
		||||
    QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls());
 | 
			
		||||
| 
						 | 
				
			
			@ -603,7 +604,7 @@ bool UserInterface::openFile(QString selectedFile, bool warn)
 | 
			
		|||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                if (warn)
 | 
			
		||||
                    QMessageBox::warning(this, tr("Open File"), ProfileInterface::tr("Failed to read Snapmatic picture"));
 | 
			
		||||
                    QMessageBox::warning(this, tr("Open File"), ProfileInterface::tr("Failed to read Photo file"));
 | 
			
		||||
                delete picture;
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -641,7 +642,7 @@ bool UserInterface::openFile(QString selectedFile, bool warn)
 | 
			
		|||
                delete savegame;
 | 
			
		||||
                delete picture;
 | 
			
		||||
                if (warn)
 | 
			
		||||
                    QMessageBox::warning(this, tr("Open File"), tr("Can't open %1 because of not valid file format").arg("\""+selectedFileName+"\""));
 | 
			
		||||
                    QMessageBox::warning(this, tr("Open File"), tr("Can not open %1 because file format is not valid").arg("\""+selectedFileName+"\""));
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
Subproject commit 302be665e2bdd6fb00628ad6310b161dcf8c834d
 | 
			
		||||
Subproject commit 933918454f16af118a3cb9e1359a00bca589d7e7
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue