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); |     const QStringList files = dir.entryList(QDir::Files); | ||||||
|     for (const QString &fileName : 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; |             t_savegameFiles << fileName; | ||||||
|             if (!savegameFiles.contains(fileName)) { |             if (!savegameFiles.contains(fileName)) { | ||||||
|                 n_savegameFiles << fileName; |                 n_savegameFiles << fileName; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (fileName.startsWith("PGTA5") && !fileName.endsWith(".bak")) { |         if ((fileName.startsWith("PGTA5") || fileName.startsWith("PRDR3")) && !fileName.endsWith(".bak")) { | ||||||
|             t_snapmaticPics << fileName; |             t_snapmaticPics << fileName; | ||||||
|             if (fileName.endsWith(".hidden")) { |             if (fileName.endsWith(".hidden")) { | ||||||
|                 const QString originalFileName = fileName.left(fileName.length() - 7); |                 const QString originalFileName = fileName.left(fileName.length() - 7); | ||||||
|  | @ -559,18 +559,18 @@ fileDialogPreOpen: //Work? | ||||||
|     for (const QByteArray &imageFormat : QImageReader::supportedImageFormats()) { |     for (const QByteArray &imageFormat : QImageReader::supportedImageFormats()) { | ||||||
|         imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " "; |         imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " "; | ||||||
|     } |     } | ||||||
|     QString importableFormatsStr = QString("*.g5e SGTA* PGTA*"); |     QString importableFormatsStr = QString("*.g5e SGTA5* PGTA5*"); | ||||||
|     if (!imageFormatsStr.trimmed().isEmpty()) { |     if (!imageFormatsStr.trimmed().isEmpty()) { | ||||||
|         importableFormatsStr = QString("*.g5e%1SGTA* PGTA*").arg(imageFormatsStr); |         importableFormatsStr = QString("*.g5e%1SGTA5* PGTA5*").arg(imageFormatsStr); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     QStringList filters; |     QStringList filters; | ||||||
|     filters << tr("Importable files (%1)").arg(importableFormatsStr); |     filters << tr("All importable files (%1)").arg(importableFormatsStr); | ||||||
|     filters << tr("GTA V Export (*.g5e)"); |     filters << tr("GTA V Export (%1)").arg("*.g5e"); | ||||||
|     filters << tr("Savegames files (SGTA*)"); |     filters << tr("GTA V Savegames files (%1)").arg("SGTA5*"); | ||||||
|     filters << tr("Snapmatic pictures (PGTA*)"); |     filters << tr("GTA V Snapmatic files (%1)").arg("PGTA5*"); | ||||||
|     filters << tr("All image files (%1)").arg(imageFormatsStr.trimmed()); |     filters << tr("All image files (%1)").arg(imageFormatsStr.trimmed()); | ||||||
|     filters << tr("All files (**)"); |     filters << tr("All files (%1)").arg("**"); | ||||||
|     fileDialog.setNameFilters(filters); |     fileDialog.setNameFilters(filters); | ||||||
| 
 | 
 | ||||||
|     QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls()); |     QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls()); | ||||||
|  | @ -796,15 +796,8 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime | ||||||
|                         cEnough++; |                         cEnough++; | ||||||
|                     } |                     } | ||||||
|                     spJson.createdDateTime = importDateTime; |                     spJson.createdDateTime = importDateTime; | ||||||
| #if QT_VERSION >= 0x060000 |                     qint64 timestamp = spJson.createdDateTime.toSecsSinceEpoch(); | ||||||
|                     quint64 timestamp = spJson.createdDateTime.toSecsSinceEpoch(); |                     spJson.createdTimestamp = timestamp; | ||||||
|                     if (timestamp > UINT32_MAX) { |  | ||||||
|                         timestamp = UINT32_MAX; |  | ||||||
|                     } |  | ||||||
|                     spJson.createdTimestamp = (quint32)timestamp; |  | ||||||
| #else |  | ||||||
|                     spJson.createdTimestamp = spJson.createdDateTime.toTime_t(); |  | ||||||
| #endif |  | ||||||
|                     picture->setSnapmaticProperties(spJson); |                     picture->setSnapmaticProperties(spJson); | ||||||
|                     const QString picFileName = QString("PGTA5%1").arg(QString::number(spJson.uid)); |                     const QString picFileName = QString("PGTA5%1").arg(QString::number(spJson.uid)); | ||||||
|                     picture->setPicFileName(picFileName); |                     picture->setPicFileName(picFileName); | ||||||
|  | @ -854,15 +847,8 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime | ||||||
|                                 cEnough++; |                                 cEnough++; | ||||||
|                             } |                             } | ||||||
|                             spJson.createdDateTime = importDateTime; |                             spJson.createdDateTime = importDateTime; | ||||||
| #if QT_VERSION >= 0x060000 |                             qint64 timestamp = spJson.createdDateTime.toSecsSinceEpoch(); | ||||||
|                             quint64 timestamp = spJson.createdDateTime.toSecsSinceEpoch(); |                             spJson.createdTimestamp = timestamp; | ||||||
|                             if (timestamp > UINT32_MAX) { |  | ||||||
|                                 timestamp = UINT32_MAX; |  | ||||||
|                             } |  | ||||||
|                             spJson.createdTimestamp = (quint32)timestamp; |  | ||||||
| #else |  | ||||||
|                             spJson.createdTimestamp = spJson.createdDateTime.toTime_t(); |  | ||||||
| #endif |  | ||||||
|                             picture->setSnapmaticProperties(spJson); |                             picture->setSnapmaticProperties(spJson); | ||||||
|                             const QString picFileName = QString("PGTA5%1").arg(QString::number(spJson.uid)); |                             const QString picFileName = QString("PGTA5%1").arg(QString::number(spJson.uid)); | ||||||
|                             picture->setPicFileName(picFileName); |                             picture->setPicFileName(picFileName); | ||||||
|  | @ -1124,15 +1110,15 @@ bool ProfileInterface::importSnapmaticPicture(SnapmaticPicture *picture, bool wa | ||||||
| { | { | ||||||
|     QString picFileName = picture->getPictureFileName(); |     QString picFileName = picture->getPictureFileName(); | ||||||
|     QString adjustedFileName = picture->getOriginalPictureFileName(); |     QString adjustedFileName = picture->getOriginalPictureFileName(); | ||||||
|     if (!picFileName.startsWith("PGTA5")) { |     if (!picFileName.startsWith("PGTA5") && !picFileName.startsWith("PRDR3")) { | ||||||
|         if (warn) |         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; |         return false; | ||||||
|     } |     } | ||||||
|     else if (QFile::exists(profileFolder % "/" % adjustedFileName) || QFile::exists(profileFolder % "/" % adjustedFileName % ".hidden")) { |     else if (QFile::exists(profileFolder % "/" % adjustedFileName) || QFile::exists(profileFolder % "/" % adjustedFileName % ".hidden")) { | ||||||
|         SnapmaticProperties snapmaticProperties = picture->getSnapmaticProperties(); |         SnapmaticProperties snapmaticProperties = picture->getSnapmaticProperties(); | ||||||
|         if (warn) { |         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) { |             if (uchoice == QMessageBox::Yes) { | ||||||
|                 // Update Snapmatic uid
 |                 // Update Snapmatic uid
 | ||||||
|                 snapmaticProperties.uid = getRandomUid(); |                 snapmaticProperties.uid = getRandomUid(); | ||||||
|  | @ -1177,15 +1163,8 @@ bool ProfileInterface::importSnapmaticPicture(SnapmaticPicture *picture, bool wa | ||||||
|             // Update Snapmatic uid
 |             // Update Snapmatic uid
 | ||||||
|             snapmaticProperties.uid = getRandomUid(); |             snapmaticProperties.uid = getRandomUid(); | ||||||
|             snapmaticProperties.createdDateTime = QDateTime::currentDateTime(); |             snapmaticProperties.createdDateTime = QDateTime::currentDateTime(); | ||||||
| #if QT_VERSION >= 0x060000 |             qint64 timestamp = snapmaticProperties.createdDateTime.toSecsSinceEpoch(); | ||||||
|             quint64 timestamp = snapmaticProperties.createdDateTime.toSecsSinceEpoch(); |             snapmaticProperties.createdTimestamp = timestamp; | ||||||
|             if (timestamp > UINT32_MAX) { |  | ||||||
|                 timestamp = UINT32_MAX; |  | ||||||
|             } |  | ||||||
|             snapmaticProperties.createdTimestamp = (quint32)timestamp; |  | ||||||
| #else |  | ||||||
|             snapmaticProperties.createdTimestamp = snapmaticProperties.createdDateTime.toTime_t(); |  | ||||||
| #endif |  | ||||||
|             bool fExists = QFile::exists(profileFolder % "/PGTA5" % QString::number(snapmaticProperties.uid)); |             bool fExists = QFile::exists(profileFolder % "/PGTA5" % QString::number(snapmaticProperties.uid)); | ||||||
|             bool fExistsBackup = QFile::exists(profileFolder % "/PGTA5" % QString::number(snapmaticProperties.uid) % ".bak"); |             bool fExistsBackup = QFile::exists(profileFolder % "/PGTA5" % QString::number(snapmaticProperties.uid) % ".bak"); | ||||||
|             bool fExistsHidden = QFile::exists(profileFolder % "/PGTA5" % QString::number(snapmaticProperties.uid) % ".hidden"); |             bool fExistsHidden = QFile::exists(profileFolder % "/PGTA5" % QString::number(snapmaticProperties.uid) % ".hidden"); | ||||||
|  | @ -1219,7 +1198,7 @@ bool ProfileInterface::importSnapmaticPicture(SnapmaticPicture *picture, bool wa | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         if (warn) |         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; |         return false; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -1255,13 +1234,13 @@ bool ProfileInterface::importSavegameData(SavegameData *savegame, QString sgdPat | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             if (warn) |             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; |             return false; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         if (warn) |         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; |         return false; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -45,40 +45,18 @@ void ProfileLoader::run() | ||||||
|     QVector<QString> savegameFiles; |     QVector<QString> savegameFiles; | ||||||
|     QVector<QString> snapmaticPics; |     QVector<QString> snapmaticPics; | ||||||
| 
 | 
 | ||||||
| #ifdef Q_OS_WIN |  | ||||||
|     QDir dir(profileFolder); |     QDir dir(profileFolder); | ||||||
|     const QStringList files = dir.entryList(QDir::Files); |     const QStringList files = dir.entryList(QDir::Files); | ||||||
|     for (const QString &fileName : 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; |             savegameFiles << fileName; | ||||||
|             maximumV++; |             maximumV++; | ||||||
|         } |         } | ||||||
|         if (fileName.startsWith("PGTA5") && !fileName.endsWith(".bak")) { |         if ((fileName.startsWith("PGTA5") || fileName.startsWith("PRDR3")) && !fileName.endsWith(".bak")) { | ||||||
|             snapmaticPics << fileName; |             snapmaticPics << fileName; | ||||||
|             maximumV++; |             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
 |     // Directory successfully scanned
 | ||||||
|     emit directoryScanned(savegameFiles, snapmaticPics); |     emit directoryScanned(savegameFiles, snapmaticPics); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /*****************************************************************************
 | /*****************************************************************************
 | ||||||
| * gta5view Grand Theft Auto V Profile Viewer | * 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 | * 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 | * it under the terms of the GNU General Public License as published by | ||||||
|  | @ -24,7 +24,8 @@ | ||||||
| #include <QFile> | #include <QFile> | ||||||
| 
 | 
 | ||||||
| #define savegameHeaderLength 260 | #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) | SavegameData::SavegameData(const QString &fileName, QObject *parent) : QObject(parent), savegameFileName(fileName) | ||||||
| { | { | ||||||
|  | @ -57,13 +58,10 @@ bool SavegameData::readingSavegame() | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     QByteArray savegameHeaderLine = saveFile->read(savegameHeaderLength); |     QByteArray savegameHeaderLine = saveFile->read(savegameHeaderLength); | ||||||
|     if (savegameHeaderLine.left(4) == verificationValue) |     if (savegameHeaderLine.startsWith(verificationValue_GTA5) || savegameHeaderLine.startsWith(verificationValue_RDR2)) { | ||||||
|     { |  | ||||||
|         savegameStr = getSavegameDataString(savegameHeaderLine); |         savegameStr = getSavegameDataString(savegameHeaderLine); | ||||||
|         if (savegameStr.length() >= 1) |         if (savegameStr.length() >= 1) | ||||||
|         { |  | ||||||
|             savegameOk = true; |             savegameOk = true; | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     saveFile->close(); |     saveFile->close(); | ||||||
|     saveFile->deleteLater(); |     saveFile->deleteLater(); | ||||||
|  | @ -74,7 +72,12 @@ bool SavegameData::readingSavegame() | ||||||
| QString SavegameData::getSavegameDataString(const QByteArray &savegameHeader) | QString SavegameData::getSavegameDataString(const QByteArray &savegameHeader) | ||||||
| { | { | ||||||
|     QByteArray savegameBytes = savegameHeader.left(savegameHeaderLength); |     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); |     savegameBytes = savegameBytesList.at(1); | ||||||
|     savegameBytesList.clear(); |     savegameBytesList.clear(); | ||||||
|     return SnapmaticPicture::parseTitleString(savegameBytes); |     return SnapmaticPicture::parseTitleString(savegameBytes); | ||||||
|  | @ -82,15 +85,12 @@ QString SavegameData::getSavegameDataString(const QByteArray &savegameHeader) | ||||||
| 
 | 
 | ||||||
| bool SavegameData::readingSavegameFromFile(const QString &fileName) | bool SavegameData::readingSavegameFromFile(const QString &fileName) | ||||||
| { | { | ||||||
|     if (fileName != "") |     if (fileName != "") { | ||||||
|     { |  | ||||||
|         savegameFileName = fileName; |         savegameFileName = fileName; | ||||||
|         return readingSavegame(); |         return readingSavegame(); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |  | ||||||
|         return false; |         return false; | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool SavegameData::isSavegameOk() | bool SavegameData::isSavegameOk() | ||||||
|  |  | ||||||
|  | @ -564,11 +564,12 @@ fileDialogPreOpen: | ||||||
|     fileDialog.setWindowTitle(tr("Open File...")); |     fileDialog.setWindowTitle(tr("Open File...")); | ||||||
| 
 | 
 | ||||||
|     QStringList filters; |     QStringList filters; | ||||||
|     filters << ProfileInterface::tr("All profile files (*.g5e SGTA* PGTA*)"); |     filters << ProfileInterface::tr("All profile files (%1)").arg("*.g5e SGTA5* PGTA5* PRDR3*"); | ||||||
|     filters << ProfileInterface::tr("GTA V Export (*.g5e)"); |     filters << ProfileInterface::tr("GTA V Export (%1)").arg("*.g5e"); | ||||||
|     filters << ProfileInterface::tr("Savegames files (SGTA*)"); |     filters << ProfileInterface::tr("GTA V Savegames files (%1)").arg("SGTA5*"); | ||||||
|     filters << ProfileInterface::tr("Snapmatic pictures (PGTA*)"); |     filters << ProfileInterface::tr("GTA V Snapmatic files (%1)").arg("PGTA5*"); | ||||||
|     filters << ProfileInterface::tr("All files (**)"); |     filters << ProfileInterface::tr("RDR 2 Photo files (%1)").arg("PRDR3*"); | ||||||
|  |     filters << ProfileInterface::tr("All files (%1)").arg("**"); | ||||||
|     fileDialog.setNameFilters(filters); |     fileDialog.setNameFilters(filters); | ||||||
| 
 | 
 | ||||||
|     QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls()); |     QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls()); | ||||||
|  | @ -603,7 +604,7 @@ bool UserInterface::openFile(QString selectedFile, bool warn) | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 if (warn) |                 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; |                 delete picture; | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|  | @ -641,7 +642,7 @@ bool UserInterface::openFile(QString selectedFile, bool warn) | ||||||
|                 delete savegame; |                 delete savegame; | ||||||
|                 delete picture; |                 delete picture; | ||||||
|                 if (warn) |                 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; |                 return false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| Subproject commit 302be665e2bdd6fb00628ad6310b161dcf8c834d | Subproject commit 933918454f16af118a3cb9e1359a00bca589d7e7 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue