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));
249 static void updateDisplayRom(
const QString& romname,
int display,
const QString& Systemname)
252 query.
prepare(
"UPDATE gamemetadata SET display = :DISPLAY "
253 "WHERE romname = :ROMNAME AND `system` = :SYSTEM");
267 query.
prepare(
"UPDATE gamemetadata SET diskcount = :DISKCOUNT "
268 "WHERE romname = :ROMNAME AND gametype = :GAMETYPE ");
279 static void updateGameName(
const QString& romname,
const QString& GameName,
const QString& Systemname)
282 query.
prepare(
"UPDATE gamemetadata SET GameName = :GAMENAME "
283 "WHERE romname = :ROMNAME AND `system` = :SYSTEM ");
299 static const QRegularExpression multiDiskRGXP {
"[0-4]$" };
305 for (
const auto &
GameType : std::as_const(updatelist))
307 LOG(VB_GENERAL, LOG_NOTICE,
308 LOC + QString(
"Update gametype %1").arg(
GameType));
310 query.
prepare(
"SELECT romname,`system`,spandisks,gamename FROM "
311 "gamemetadata,gameplayers WHERE "
312 "gamemetadata.gametype = :GAMETYPE AND "
313 "playername = `system` ORDER BY romname");
321 QString RomName = query.
value(0).toString();
322 QString System = query.
value(1).toString();
323 int spandisks = query.
value(2).toInt();
324 QString GameName = query.
value(3).toString();
332 int pos = RomName.lastIndexOf(
".");
335 extlength = RomName.length() - pos;
338 basename = RomName.mid(pos,1);
341 if (basename.contains(multiDiskRGXP))
343 pos = (RomName.length() - extlength) - 1;
344 basename = RomName.left(pos);
346 if (basename.right(1) ==
".")
347 basename = RomName.left(pos - 1);
352 if (basename == lastrom)
365 if (basename != GameName)
370 if (basename == lastrom)
386 QString message = tr(
"Updating %1 (%2) ROM database")
410 for (
const auto & game : std::as_const(
m_gameMap))
417 GetMetadata(handler, game.RomFullPath(), &Genre, &Year, &Country, &CRC32, &GameName,
418 &Plot, &Publisher, &Version, &Fanart, &Boxart);
424 Genre = tr(
"Unknown %1",
"Unknown genre").arg(handler->
GameType());
425 Country = tr(
"Unknown",
"Unknown country");
427 Year = tr(
"19xx",
"Default game year");
428 GameName = tr(
"Unknown",
"Unknown game name");
429 Plot = tr(
"Unknown",
"Unknown plot");
430 Publisher = tr(
"Unknown",
"Unknown publisher");
431 Version = tr(
"0",
"Default game version");
436 if (GameName == tr(
"Unknown",
"Unknown game name"))
437 GameName = game.GameName();
439 int suffixPos = game.Rom().lastIndexOf(QChar(
'.'));
440 QString baseName = game.Rom();
443 baseName = game.Rom().left(suffixPos);
445 baseName = screenShotPath +
"/" + baseName;
447 if (QFile(baseName +
".png").exists())
448 ScreenShot = baseName +
".png";
449 else if (QFile(baseName +
".jpg").exists())
450 ScreenShot = baseName +
".jpg";
451 else if (QFile(baseName +
".gif").exists())
452 ScreenShot = baseName +
".gif";
457 LOG(VB_GENERAL, LOG_INFO, QString(
"file %1 - genre %2 ")
458 .arg(iter.data().Rom()).arg(Genre));
459 LOG(VB_GENERAL, LOG_INFO, QString(
"screenshot %1").arg(ScreenShot));
462 query.
prepare(
"INSERT INTO gamemetadata "
463 "(`system`, romname, gamename, genre, year, gametype, "
464 "rompath, country, crc_value, diskcount, display, plot, "
465 "publisher, version, fanart, boxart, screenshot) "
466 "VALUES (:SYSTEM, :ROMNAME, :GAMENAME, :GENRE, :YEAR, "
467 ":GAMETYPE, :ROMPATH, :COUNTRY, :CRC32, '1', '1', :PLOT, :PUBLISHER, :VERSION, "
468 ":FANART, :BOXART, :SCREENSHOT)");
488 "insert gamemetadata", query);
490 else if ((game.FoundLoc() ==
inDatabase) && (removalprompt))
512 query.
prepare(
"SELECT romname,rompath,gamename FROM gamemetadata "
513 "WHERE `system` = :SYSTEM");
522 QString message = tr(
"Verifying %1 files...").arg(handler->
SystemName());
532 QString RomName = query.
value(0).toString();
534 QString GameName = query.
value(2).toString();
535 if (!RomName.isEmpty())
537 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
540 auto iter =
m_gameMap.constFind(RomName);
571 QDir RomDir(directory);
574 if (!RomDir.isReadable())
577 RomDir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
578 QFileInfoList List = RomDir.entryInfoList();
579 for (
const auto & Info : std::as_const(List))
589 QRegularExpression r {
590 "^" + Info.suffix() +
"$",
591 QRegularExpression::CaseInsensitiveOption };
594 std::copy_if(exts.cbegin(), exts.cend(), std::back_inserter(result),
595 [&r](
const QString& extension){ return extension.contains(r); } );
596 if (result.isEmpty())
610 tr(
"This will clear all game metadata from the database. Are you sure "
611 "you want to do this?"), popupStack,
"clearAllPopup");
613 if (clearPopup->Create())
615 clearPopup->SetReturnEvent(
this,
"clearAllPopup");
616 clearPopup->AddButton(tr(
"No"));
617 clearPopup->AddButton(tr(
"Yes"));
627 QDir RomDir(directory);
630 if (!RomDir.isReadable())
633 RomDir.setSorting( QDir:: DirsFirst | QDir::Name );
634 RomDir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
635 QFileInfoList List = RomDir.entryInfoList();
636 for (
const auto & Info : std::as_const(List))
638 QString RomName = Info.fileName();
639 QString GameName = Info.completeBaseName();
649 QRegularExpression r {
650 "^" + Info.suffix() +
"$",
651 QRegularExpression::CaseInsensitiveOption };
654 std::copy_if(exts.cbegin(), exts.cend(), std::back_inserter(result),
655 [&r](
const QString& extension){ return extension.contains(r); } );
656 if (result.isEmpty())
661 GameName, Info.absoluteDir().path());
663 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Found ROM : (%1) - %2")
666 *filecount = *filecount + 1;
684 LOG(VB_GENERAL, LOG_ERR,
LOC +
685 QString(
"ROM Path does not exist: %1")
698 QString message = tr(
"Scanning for %1 games...")
703 if (busyDialog->Create())
704 popupStack->
AddScreen(busyDialog,
false);
708 busyDialog =
nullptr;
721 LOG(VB_GENERAL, LOG_INFO,
LOC +
722 QString(
"PC Game %1").arg(handler->
SystemName()));
726 QString message = tr(
"Scanning for %1 games...")
762 QStringList updatelist;
764 for (
auto *handler : std::as_const(*
handlers))
769 handler->processGames(handler);
771 if (handler->needRebuild())
772 updatelist.append(handler->GameType());
776 if (!updatelist.isEmpty())
785 for (
auto *handler : std::as_const(*
handlers))
789 if (rominfo->
System() == handler->SystemName())
799 if (systemname.isEmpty())
802 for (
auto *handler : std::as_const(*
handlers))
806 if (handler->SystemName() == systemname)
818 if (!systemname.isEmpty())
825 if (handler ==
nullptr)
838 QString arg =
"\"" + romdata->
Rompath() +
839 "/" + romdata->
Romname() +
"\"";
844 if (exec.contains(
"%s") || handler->
SpanDisks())
846 exec = exec.replace(
"%s",arg);
850 static const QRegularExpression rxp {
"%d[0-4]" };
852 if (exec.contains(rxp))
860 std::array<QString,7> diskid {
"%d0",
"%d1",
"%d2",
"%d3",
"%d4",
"%d5",
"%d6" };
862 for (
int disk = 1; disk <= romdata->
DiskCount(); disk++)
864 rom = QString(
"\"%1/%2%3.%4\"")
865 .arg(romdata->
Rompath(), basename,
866 QString::number(disk), extension);
867 exec = exec.replace(diskid[disk],rom);
871 exec = exec.replace(
"%d1",arg);
878 exec = exec +
" \"" +
890 LOG(VB_GENERAL, LOG_ERR,
LOC +
891 QString(
"Failed to change to specified Working Directory: %1")
895 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Launching Game : %1 : %2")
901 QStringList cmdlist = exec.split(
";");
902 if (cmdlist.count() > 0)
904 for (
const auto & cmd : std::as_const(cmdlist))
906 LOG(VB_GENERAL, LOG_INFO,
LOC +
907 QString(
"Executing : %1").arg(cmd));
913 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Executing : %1").arg(exec));
939 QString resultid = dce->GetId();
942 if (resultid ==
"removalPopup")
944 int buttonNum = dce->GetResult();
962 else if (resultid ==
"clearAllPopup")
964 int buttonNum = dce->GetResult();
980 if (!query.
exec(
"DELETE FROM gamemetadata;"))
982 "delete gamemetadata", query);