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,14 +58,11 @@ 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(); | ||||
|     delete saveFile; | ||||
|  | @ -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