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 ");
77 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
79 .remove(
" ").split(
",", QString::SkipEmptyParts);
82 .remove(
" ").split(
",", Qt::SkipEmptyParts);
112 query.
prepare(
"SELECT crc, category, year, country, name, "
113 "description, publisher, platform, version, "
114 "binfile FROM romdb WHERE platform = :GAMETYPE;");
122 key = QString(
"%1:%2")
123 .arg(query.
value(0).toString(),
124 query.
value(9).toString());
126 query.
value(1).toString(),
127 query.
value(2).toString(),
128 query.
value(3).toString(),
129 query.
value(4).toString(),
130 query.
value(5).toString(),
131 query.
value(6).toString(),
132 query.
value(7).toString(),
133 query.
value(8).toString());
139 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"No romDB data read from "
140 "database for gametype %1 . Not imported?").arg(
GameType));
144 LOG(VB_GENERAL, LOG_INFO,
LOC +
145 QString(
"Loaded %1 items from romDB Database") .arg(
m_romDB.count()));
150 QString* Country, QString* CRC32, QString* GameName,
151 QString *Plot, QString *Publisher, QString *Version,
152 QString* Fanart, QString* Boxart)
159 LOG(VB_GENERAL, LOG_DEBUG,
"Key = " + key);
163 *Year = tr(
"19xx",
"Default game year");
164 *Country = tr(
"Unknown",
"Unknown country");
165 *GameName = tr(
"Unknown",
"Unknown game name");
166 *Genre = tr(
"Unknown",
"Unknown genre");
167 *Plot = tr(
"Unknown",
"Unknown plot");
168 *Publisher = tr(
"Unknown",
"Unknown publisher");
169 *Version = tr(
"0",
"Default game version");
173 if (!(*CRC32).isEmpty())
177 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"ROMDB FOUND for %1 - %2")
178 .arg(
m_romDB[key].GameName(), key));
180 *Country =
m_romDB[key].Country();
182 *Publisher =
m_romDB[key].Publisher();
183 *GameName =
m_romDB[key].GameName();
184 *Version =
m_romDB[key].Version();
188 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"NO ROMDB FOUND for %1 (%2)")
194 if ((*Genre == tr(
"Unknown",
"Unknown genre")) || (*Genre).isEmpty())
195 *Genre = tr(
"Unknown %1",
"Unknown genre")
202 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Purging %1 - %2")
210 query.
prepare(
"DELETE FROM gamemetadata WHERE "
211 "romname = :ROMNAME AND "
212 "rompath = :ROMPATH ");
236 tr(
"%1 appears to be missing.\n"
237 "Remove it from the database?")
238 .arg(
filename), popupStack,
"chooseSystemPopup");
240 if (removalPopup->Create())
242 removalPopup->SetReturnEvent(
this,
"removalPopup");
244 removalPopup->AddButton(tr(
"No"));
245 removalPopup->AddButton(tr(
"No to all"));
246 removalPopup->AddButtonV(tr(
"Yes"), QVariant::fromValue(
scan));
247 removalPopup->AddButtonV(tr(
"Yes to all"), QVariant::fromValue(
scan));
254 static void updateDisplayRom(
const QString& romname,
int display,
const QString& Systemname)
257 query.
prepare(
"UPDATE gamemetadata SET display = :DISPLAY "
258 "WHERE romname = :ROMNAME AND `system` = :SYSTEM");
272 query.
prepare(
"UPDATE gamemetadata SET diskcount = :DISKCOUNT "
273 "WHERE romname = :ROMNAME AND gametype = :GAMETYPE ");
284 static void updateGameName(
const QString& romname,
const QString& GameName,
const QString& Systemname)
287 query.
prepare(
"UPDATE gamemetadata SET GameName = :GAMENAME "
288 "WHERE romname = :ROMNAME AND `system` = :SYSTEM ");
304 static const QRegularExpression multiDiskRGXP {
"[0-4]$" };
310 for (
const auto &
GameType : qAsConst(updatelist))
312 LOG(VB_GENERAL, LOG_NOTICE,
313 LOC + QString(
"Update gametype %1").arg(
GameType));
315 query.
prepare(
"SELECT romname,`system`,spandisks,gamename FROM "
316 "gamemetadata,gameplayers WHERE "
317 "gamemetadata.gametype = :GAMETYPE AND "
318 "playername = `system` ORDER BY romname");
326 QString RomName = query.
value(0).toString();
327 QString System = query.
value(1).toString();
328 int spandisks = query.
value(2).toInt();
329 QString GameName = query.
value(3).toString();
337 int pos = RomName.lastIndexOf(
".");
340 extlength = RomName.length() - pos;
343 basename = RomName.mid(pos,1);
346 if (basename.contains(multiDiskRGXP))
348 pos = (RomName.length() - extlength) - 1;
349 basename = RomName.left(pos);
351 if (basename.right(1) ==
".")
352 basename = RomName.left(pos - 1);
357 if (basename == lastrom)
370 if (basename != GameName)
375 if (basename == lastrom)
391 QString message = tr(
"Updating %1 (%2) ROM database")
415 for (
const auto & game : qAsConst(
m_gameMap))
422 GetMetadata(handler, game.RomFullPath(), &Genre, &Year, &Country, &CRC32, &GameName,
423 &Plot, &Publisher, &Version, &Fanart, &Boxart);
429 Genre = tr(
"Unknown %1",
"Unknown genre").arg(handler->
GameType());
430 Country = tr(
"Unknown",
"Unknown country");
432 Year = tr(
"19xx",
"Default game year");
433 GameName = tr(
"Unknown",
"Unknown game name");
434 Plot = tr(
"Unknown",
"Unknown plot");
435 Publisher = tr(
"Unknown",
"Unknown publisher");
436 Version = tr(
"0",
"Default game version");
441 if (GameName == tr(
"Unknown",
"Unknown game name"))
442 GameName = game.GameName();
444 int suffixPos = game.Rom().lastIndexOf(QChar(
'.'));
445 QString baseName = game.Rom();
448 baseName = game.Rom().left(suffixPos);
450 baseName = screenShotPath +
"/" + baseName;
452 if (QFile(baseName +
".png").exists())
453 ScreenShot = baseName +
".png";
454 else if (QFile(baseName +
".jpg").exists())
455 ScreenShot = baseName +
".jpg";
456 else if (QFile(baseName +
".gif").exists())
457 ScreenShot = baseName +
".gif";
462 LOG(VB_GENERAL, LOG_INFO, QString(
"file %1 - genre %2 ")
463 .arg(iter.data().Rom()).arg(Genre));
464 LOG(VB_GENERAL, LOG_INFO, QString(
"screenshot %1").arg(ScreenShot));
467 query.
prepare(
"INSERT INTO gamemetadata "
468 "(`system`, romname, gamename, genre, year, gametype, "
469 "rompath, country, crc_value, diskcount, display, plot, "
470 "publisher, version, fanart, boxart, screenshot) "
471 "VALUES (:SYSTEM, :ROMNAME, :GAMENAME, :GENRE, :YEAR, "
472 ":GAMETYPE, :ROMPATH, :COUNTRY, :CRC32, '1', '1', :PLOT, :PUBLISHER, :VERSION, "
473 ":FANART, :BOXART, :SCREENSHOT)");
493 "insert gamemetadata", query);
495 else if ((game.FoundLoc() ==
inDatabase) && (removalprompt))
517 query.
prepare(
"SELECT romname,rompath,gamename FROM gamemetadata "
518 "WHERE `system` = :SYSTEM");
527 QString message = tr(
"Verifying %1 files...").arg(handler->
SystemName());
537 QString RomName = query.
value(0).toString();
539 QString GameName = query.
value(2).toString();
540 if (!RomName.isEmpty())
542 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
545 auto iter =
m_gameMap.constFind(RomName);
576 QDir RomDir(directory);
579 if (!RomDir.isReadable())
582 RomDir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
583 QFileInfoList List = RomDir.entryInfoList();
584 for (
const auto & Info : qAsConst(List))
594 QRegularExpression r {
595 "^" + Info.suffix() +
"$",
596 QRegularExpression::CaseInsensitiveOption };
599 std::copy_if(exts.cbegin(), exts.cend(), std::back_inserter(result),
600 [&r](
const QString& extension){ return extension.contains(r); } );
601 if (result.isEmpty())
615 tr(
"This will clear all game metadata from the database. Are you sure "
616 "you want to do this?"), popupStack,
"clearAllPopup");
618 if (clearPopup->Create())
620 clearPopup->SetReturnEvent(
this,
"clearAllPopup");
621 clearPopup->AddButton(tr(
"No"));
622 clearPopup->AddButton(tr(
"Yes"));
632 QDir RomDir(directory);
635 if (!RomDir.isReadable())
638 RomDir.setSorting( QDir:: DirsFirst | QDir::Name );
639 RomDir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
640 QFileInfoList List = RomDir.entryInfoList();
641 for (
const auto & Info : qAsConst(List))
643 QString RomName = Info.fileName();
644 QString GameName = Info.completeBaseName();
654 QRegularExpression r {
655 "^" + Info.suffix() +
"$",
656 QRegularExpression::CaseInsensitiveOption };
659 std::copy_if(exts.cbegin(), exts.cend(), std::back_inserter(result),
660 [&r](
const QString& extension){ return extension.contains(r); } );
661 if (result.isEmpty())
666 GameName, Info.absoluteDir().path());
668 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Found ROM : (%1) - %2")
671 *filecount = *filecount + 1;
689 LOG(VB_GENERAL, LOG_ERR,
LOC +
690 QString(
"ROM Path does not exist: %1")
703 QString message = tr(
"Scanning for %1 games...")
708 if (busyDialog->Create())
709 popupStack->
AddScreen(busyDialog,
false);
713 busyDialog =
nullptr;
726 LOG(VB_GENERAL, LOG_INFO,
LOC +
727 QString(
"PC Game %1").arg(handler->
SystemName()));
731 QString message = tr(
"Scanning for %1 games...")
767 QStringList updatelist;
769 for (
auto *handler : qAsConst(*
handlers))
774 handler->processGames(handler);
776 if (handler->needRebuild())
777 updatelist.append(handler->GameType());
781 if (!updatelist.isEmpty())
790 for (
auto *handler : qAsConst(*
handlers))
794 if (rominfo->
System() == handler->SystemName())
804 if (systemname.isEmpty())
807 for (
auto *handler : qAsConst(*
handlers))
811 if (handler->SystemName() == systemname)
823 if (!systemname.isEmpty())
839 QString arg =
"\"" + romdata->
Rompath() +
840 "/" + romdata->
Romname() +
"\"";
845 if (exec.contains(
"%s") || handler->
SpanDisks())
847 exec = exec.replace(
"%s",arg);
851 static const QRegularExpression rxp {
"%d[0-4]" };
853 if (exec.contains(rxp))
861 std::array<QString,7> diskid {
"%d0",
"%d1",
"%d2",
"%d3",
"%d4",
"%d5",
"%d6" };
863 for (
int disk = 1; disk <= romdata->
DiskCount(); disk++)
865 rom = QString(
"\"%1/%2%3.%4\"")
866 .arg(romdata->
Rompath(), basename,
867 QString::number(disk), extension);
868 exec = exec.replace(diskid[disk],rom);
872 exec = exec.replace(
"%d1",arg);
879 exec = exec +
" \"" +
891 LOG(VB_GENERAL, LOG_ERR,
LOC +
892 QString(
"Failed to change to specified Working Directory: %1")
896 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Launching Game : %1 : %2")
902 QStringList cmdlist = exec.split(
";");
903 if (cmdlist.count() > 0)
905 for (
const auto & cmd : qAsConst(cmdlist))
907 LOG(VB_GENERAL, LOG_INFO,
LOC +
908 QString(
"Executing : %1").arg(cmd));
914 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Executing : %1").arg(exec));
940 QString resultid = dce->GetId();
943 if (resultid ==
"removalPopup")
945 int buttonNum = dce->GetResult();
963 else if (resultid ==
"clearAllPopup")
965 int buttonNum = dce->GetResult();
981 if (!query.
exec(
"DELETE FROM gamemetadata;"))
983 "delete gamemetadata", query);