7 #include <QRegularExpression>
24 #define LOC_ERR QString("MythGame:GAMEHANDLER Error: ")
25 #define LOC QString("MythGame:GAMEHANDLER: ")
27 static QList<GameHandler*> *
handlers =
nullptr;
43 if (!query.
exec(
"SELECT DISTINCT playername FROM gameplayers "
44 "WHERE playername <> '';"))
49 QString name = query.
value(0).toString();
63 query.
prepare(
"SELECT rompath, workingpath, commandline, screenshots, "
64 "gameplayerid, gametype, extensions, spandisks "
65 "FROM gameplayers WHERE playername = :SYSTEM ");
78 .remove(
" ").split(
",", Qt::SkipEmptyParts);
107 query.
prepare(
"SELECT crc, category, year, country, name, "
108 "description, publisher, platform, version, "
109 "binfile FROM romdb WHERE platform = :GAMETYPE;");
117 key = QString(
"%1:%2")
118 .arg(query.
value(0).toString(),
119 query.
value(9).toString());
121 query.
value(1).toString(),
122 query.
value(2).toString(),
123 query.
value(3).toString(),
124 query.
value(4).toString(),
125 query.
value(5).toString(),
126 query.
value(6).toString(),
127 query.
value(7).toString(),
128 query.
value(8).toString());
134 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"No romDB data read from "
135 "database for gametype %1 . Not imported?").arg(
GameType));
139 LOG(VB_GENERAL, LOG_INFO,
LOC +
140 QString(
"Loaded %1 items from romDB Database") .arg(
m_romDB.count()));
145 QString* Country, QString* CRC32, QString* GameName,
146 QString *Plot, QString *Publisher, QString *Version,
147 QString* Fanart, QString* Boxart)
154 LOG(VB_GENERAL, LOG_DEBUG,
"Key = " + key);
158 *Year = tr(
"19xx",
"Default game year");
159 *Country = tr(
"Unknown",
"Unknown country");
160 *GameName = tr(
"Unknown",
"Unknown game name");
161 *Genre = tr(
"Unknown",
"Unknown genre");
162 *Plot = tr(
"Unknown",
"Unknown plot");
163 *Publisher = tr(
"Unknown",
"Unknown publisher");
164 *Version = tr(
"0",
"Default game version");
168 if (!(*CRC32).isEmpty())
172 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"ROMDB FOUND for %1 - %2")
173 .arg(
m_romDB[key].GameName(), key));
175 *Country =
m_romDB[key].Country();
177 *Publisher =
m_romDB[key].Publisher();
178 *GameName =
m_romDB[key].GameName();
179 *Version =
m_romDB[key].Version();
183 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"NO ROMDB FOUND for %1 (%2)")
189 if ((*Genre == tr(
"Unknown",
"Unknown genre")) || (*Genre).isEmpty())
190 *Genre = tr(
"Unknown %1",
"Unknown genre")
197 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Purging %1 - %2")
205 query.
prepare(
"DELETE FROM gamemetadata WHERE "
206 "romname = :ROMNAME AND "
207 "rompath = :ROMPATH ");
231 tr(
"%1 appears to be missing.\n"
232 "Remove it from the database?")
233 .arg(
filename), popupStack,
"chooseSystemPopup");
235 if (removalPopup->Create())
237 removalPopup->SetReturnEvent(
this,
"removalPopup");
239 removalPopup->AddButton(tr(
"No"));
240 removalPopup->AddButton(tr(
"No to all"));
241 removalPopup->AddButtonV(tr(
"Yes"), QVariant::fromValue(
scan));
242 removalPopup->AddButtonV(tr(
"Yes to all"), QVariant::fromValue(
scan));
251 static void updateDisplayRom(
const QString& romname,
int display,
const QString& Systemname)
254 query.
prepare(
"UPDATE gamemetadata SET display = :DISPLAY "
255 "WHERE romname = :ROMNAME AND `system` = :SYSTEM");
269 query.
prepare(
"UPDATE gamemetadata SET diskcount = :DISKCOUNT "
270 "WHERE romname = :ROMNAME AND gametype = :GAMETYPE ");
281 static void updateGameName(
const QString& romname,
const QString& GameName,
const QString& Systemname)
284 query.
prepare(
"UPDATE gamemetadata SET GameName = :GAMENAME "
285 "WHERE romname = :ROMNAME AND `system` = :SYSTEM ");
301 static const QRegularExpression multiDiskRGXP {
"[0-4]$" };
307 for (
const auto &
GameType : std::as_const(updatelist))
309 LOG(VB_GENERAL, LOG_NOTICE,
310 LOC + QString(
"Update gametype %1").arg(
GameType));
312 query.
prepare(
"SELECT romname,`system`,spandisks,gamename FROM "
313 "gamemetadata,gameplayers WHERE "
314 "gamemetadata.gametype = :GAMETYPE AND "
315 "playername = `system` ORDER BY romname");
323 QString RomName = query.
value(0).toString();
324 QString System = query.
value(1).toString();
325 int spandisks = query.
value(2).toInt();
326 QString GameName = query.
value(3).toString();
334 int pos = RomName.lastIndexOf(
".");
337 extlength = RomName.length() - pos;
340 basename = RomName.mid(pos,1);
343 if (basename.contains(multiDiskRGXP))
345 pos = (RomName.length() - extlength) - 1;
346 basename = RomName.left(pos);
348 if (basename.right(1) ==
".")
349 basename = RomName.left(pos - 1);
356 if (basename == lastrom)
369 if (basename != GameName)
374 if (basename == lastrom)
390 QString message = tr(
"Updating %1 (%2) ROM database")
414 for (
const auto & game : std::as_const(
m_gameMap))
421 GetMetadata(handler, game.RomFullPath(), &Genre, &Year, &Country, &CRC32, &GameName,
422 &Plot, &Publisher, &Version, &Fanart, &Boxart);
428 Genre = tr(
"Unknown %1",
"Unknown genre").arg(handler->
GameType());
429 Country = tr(
"Unknown",
"Unknown country");
431 Year = tr(
"19xx",
"Default game year");
432 GameName = tr(
"Unknown",
"Unknown game name");
433 Plot = tr(
"Unknown",
"Unknown plot");
434 Publisher = tr(
"Unknown",
"Unknown publisher");
435 Version = tr(
"0",
"Default game version");
440 if (GameName == tr(
"Unknown",
"Unknown game name"))
441 GameName = game.GameName();
443 int suffixPos = game.Rom().lastIndexOf(QChar(
'.'));
444 QString baseName = game.Rom();
447 baseName = game.Rom().left(suffixPos);
449 baseName = screenShotPath +
"/" + baseName;
451 if (QFile(baseName +
".png").
exists())
452 ScreenShot = baseName +
".png";
453 else if (QFile(baseName +
".jpg").
exists())
454 ScreenShot = baseName +
".jpg";
455 else if (QFile(baseName +
".gif").
exists())
456 ScreenShot = baseName +
".gif";
461 LOG(VB_GENERAL, LOG_INFO, QString(
"file %1 - genre %2 ")
462 .arg(iter.data().Rom()).arg(Genre));
463 LOG(VB_GENERAL, LOG_INFO, QString(
"screenshot %1").arg(ScreenShot));
466 query.
prepare(
"INSERT INTO gamemetadata "
467 "(`system`, romname, gamename, genre, year, gametype, "
468 "rompath, country, crc_value, diskcount, display, plot, "
469 "publisher, version, fanart, boxart, screenshot) "
470 "VALUES (:SYSTEM, :ROMNAME, :GAMENAME, :GENRE, :YEAR, "
471 ":GAMETYPE, :ROMPATH, :COUNTRY, :CRC32, '1', '1', :PLOT, :PUBLISHER, :VERSION, "
472 ":FANART, :BOXART, :SCREENSHOT)");
492 "insert gamemetadata", query);
494 else if ((game.FoundLoc() ==
inDatabase) && (removalprompt))
516 query.
prepare(
"SELECT romname,rompath,gamename FROM gamemetadata "
517 "WHERE `system` = :SYSTEM");
526 QString message = tr(
"Verifying %1 files...").arg(handler->
SystemName());
536 QString RomName = query.
value(0).toString();
538 QString GameName = query.
value(2).toString();
539 if (!RomName.isEmpty())
541 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
544 auto iter =
m_gameMap.constFind(RomName);
575 QDir RomDir(directory);
578 if (!RomDir.isReadable())
581 RomDir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
582 QFileInfoList List = RomDir.entryInfoList();
583 for (
const auto & Info : std::as_const(List))
593 QRegularExpression r {
594 "^" + Info.suffix() +
"$",
595 QRegularExpression::CaseInsensitiveOption };
598 std::copy_if(exts.cbegin(), exts.cend(), std::back_inserter(result),
599 [&r](
const QString& extension){ return extension.contains(r); } );
600 if (result.isEmpty())
614 tr(
"This will clear all game metadata from the database. Are you sure "
615 "you want to do this?"), popupStack,
"clearAllPopup");
617 if (clearPopup->Create())
619 clearPopup->SetReturnEvent(
this,
"clearAllPopup");
620 clearPopup->AddButton(tr(
"No"));
621 clearPopup->AddButton(tr(
"Yes"));
633 QDir RomDir(directory);
636 if (!RomDir.isReadable())
639 RomDir.setSorting( QDir:: DirsFirst | QDir::Name );
640 RomDir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
641 QFileInfoList List = RomDir.entryInfoList();
642 for (
const auto & Info : std::as_const(List))
644 QString RomName = Info.fileName();
645 QString GameName = Info.completeBaseName();
655 QRegularExpression r {
656 "^" + Info.suffix() +
"$",
657 QRegularExpression::CaseInsensitiveOption };
660 std::copy_if(exts.cbegin(), exts.cend(), std::back_inserter(result),
661 [&r](
const QString& extension){ return extension.contains(r); } );
662 if (result.isEmpty())
667 GameName, Info.absoluteDir().path());
669 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Found ROM : (%1) - %2")
672 *filecount = *filecount + 1;
690 LOG(VB_GENERAL, LOG_ERR,
LOC +
691 QString(
"ROM Path does not exist: %1")
706 QString message = tr(
"Scanning for %1 games...")
711 if (busyDialog->Create())
712 popupStack->
AddScreen(busyDialog,
false);
716 busyDialog =
nullptr;
729 LOG(VB_GENERAL, LOG_INFO,
LOC +
730 QString(
"PC Game %1").arg(handler->
SystemName()));
734 QString message = tr(
"Scanning for %1 games...")
772 QStringList updatelist;
774 for (
auto *handler : std::as_const(*
handlers))
779 handler->processGames(handler);
781 if (handler->needRebuild())
782 updatelist.append(handler->GameType());
786 if (!updatelist.isEmpty())
795 for (
auto *handler : std::as_const(*
handlers))
799 if (rominfo->
System() == handler->SystemName())
809 if (systemname.isEmpty())
812 for (
auto *handler : std::as_const(*
handlers))
816 if (handler->SystemName() == systemname)
828 if (!systemname.isEmpty())
835 if (handler ==
nullptr)
848 QString arg =
"\"" + romdata->
Rompath() +
849 "/" + romdata->
Romname() +
"\"";
854 if (exec.contains(
"%s") || handler->
SpanDisks())
856 exec = exec.replace(
"%s",arg);
860 static const QRegularExpression rxp {
"%d[0-4]" };
862 if (exec.contains(rxp))
870 std::array<QString,7> diskid {
"%d0",
"%d1",
"%d2",
"%d3",
"%d4",
"%d5",
"%d6" };
872 for (
int disk = 1; disk <= romdata->
DiskCount(); disk++)
874 rom = QString(
"\"%1/%2%3.%4\"")
875 .arg(romdata->
Rompath(), basename,
876 QString::number(disk), extension);
877 exec = exec.replace(diskid[disk],rom);
881 exec = exec.replace(
"%d1",arg);
888 exec = exec +
" \"" +
900 LOG(VB_GENERAL, LOG_ERR,
LOC +
901 QString(
"Failed to change to specified Working Directory: %1")
905 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Launching Game : %1 : %2")
911 QStringList cmdlist = exec.split(
";");
912 if (cmdlist.count() > 0)
914 for (
const auto & cmd : std::as_const(cmdlist))
916 LOG(VB_GENERAL, LOG_INFO,
LOC +
917 QString(
"Executing : %1").arg(cmd));
923 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Executing : %1").arg(exec));
949 QString resultid = dce->GetId();
952 if (resultid ==
"removalPopup")
954 int buttonNum = dce->GetResult();
972 else if (resultid ==
"clearAllPopup")
974 int buttonNum = dce->GetResult();
990 if (!query.
exec(
"DELETE FROM gamemetadata;"))
992 "delete gamemetadata", query);