7 #include <QRegularExpression>
25 #define LOC_ERR QString("MythGame:GAMEHANDLER Error: ")
26 #define LOC QString("MythGame:GAMEHANDLER: ")
28 static QList<GameHandler*> *
handlers =
nullptr;
44 if (!query.
exec(
"SELECT DISTINCT playername FROM gameplayers "
45 "WHERE playername <> '';"))
50 QString name = query.
value(0).toString();
64 query.
prepare(
"SELECT rompath, workingpath, commandline, screenshots, "
65 "gameplayerid, gametype, extensions, spandisks "
66 "FROM gameplayers WHERE playername = :SYSTEM ");
79 .remove(
" ").split(
",", Qt::SkipEmptyParts);
108 query.
prepare(
"SELECT crc, category, year, country, name, "
109 "description, publisher, platform, version, "
110 "binfile FROM romdb WHERE platform = :GAMETYPE;");
118 key = QString(
"%1:%2")
119 .arg(query.
value(0).toString(),
120 query.
value(9).toString());
122 query.
value(1).toString(),
123 query.
value(2).toString(),
124 query.
value(3).toString(),
125 query.
value(4).toString(),
126 query.
value(5).toString(),
127 query.
value(6).toString(),
128 query.
value(7).toString(),
129 query.
value(8).toString());
135 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"No romDB data read from "
136 "database for gametype %1 . Not imported?").arg(
GameType));
140 LOG(VB_GENERAL, LOG_INFO,
LOC +
141 QString(
"Loaded %1 items from romDB Database") .arg(
m_romDB.count()));
146 QString* Country, QString* CRC32, QString* GameName,
147 QString *Plot, QString *Publisher, QString *Version,
148 QString* Fanart, QString* Boxart)
155 LOG(VB_GENERAL, LOG_DEBUG,
"Key = " + key);
159 *Year = tr(
"19xx",
"Default game year");
160 *Country = tr(
"Unknown",
"Unknown country");
161 *GameName = tr(
"Unknown",
"Unknown game name");
162 *Genre = tr(
"Unknown",
"Unknown genre");
163 *Plot = tr(
"Unknown",
"Unknown plot");
164 *Publisher = tr(
"Unknown",
"Unknown publisher");
165 *Version = tr(
"0",
"Default game version");
169 if (!(*CRC32).isEmpty())
173 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"ROMDB FOUND for %1 - %2")
174 .arg(
m_romDB[key].GameName(), key));
176 *Country =
m_romDB[key].Country();
178 *Publisher =
m_romDB[key].Publisher();
179 *GameName =
m_romDB[key].GameName();
180 *Version =
m_romDB[key].Version();
184 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"NO ROMDB FOUND for %1 (%2)")
190 if ((*Genre == tr(
"Unknown",
"Unknown genre")) || (*Genre).isEmpty())
191 *Genre = tr(
"Unknown %1",
"Unknown genre")
198 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Purging %1 - %2")
206 query.
prepare(
"DELETE FROM gamemetadata WHERE "
207 "romname = :ROMNAME AND "
208 "rompath = :ROMPATH ");
232 tr(
"%1 appears to be missing.\n"
233 "Remove it from the database?")
234 .arg(
filename), popupStack,
"chooseSystemPopup");
236 if (removalPopup->Create())
238 removalPopup->SetReturnEvent(
this,
"removalPopup");
240 removalPopup->AddButton(tr(
"No"));
241 removalPopup->AddButton(tr(
"No to all"));
242 removalPopup->AddButtonV(tr(
"Yes"), QVariant::fromValue(
scan));
243 removalPopup->AddButtonV(tr(
"Yes to all"), QVariant::fromValue(
scan));
252 static void updateDisplayRom(
const QString& romname,
int display,
const QString& Systemname)
255 query.
prepare(
"UPDATE gamemetadata SET display = :DISPLAY "
256 "WHERE romname = :ROMNAME AND `system` = :SYSTEM");
270 query.
prepare(
"UPDATE gamemetadata SET diskcount = :DISKCOUNT "
271 "WHERE romname = :ROMNAME AND gametype = :GAMETYPE ");
282 static void updateGameName(
const QString& romname,
const QString& GameName,
const QString& Systemname)
285 query.
prepare(
"UPDATE gamemetadata SET GameName = :GAMENAME "
286 "WHERE romname = :ROMNAME AND `system` = :SYSTEM ");
302 static const QRegularExpression multiDiskRGXP {
"[0-4]$" };
308 for (
const auto &
GameType : std::as_const(updatelist))
310 LOG(VB_GENERAL, LOG_NOTICE,
311 LOC + QString(
"Update gametype %1").arg(
GameType));
313 query.
prepare(
"SELECT romname,`system`,spandisks,gamename FROM "
314 "gamemetadata,gameplayers WHERE "
315 "gamemetadata.gametype = :GAMETYPE AND "
316 "playername = `system` ORDER BY romname");
324 QString RomName = query.
value(0).toString();
325 QString System = query.
value(1).toString();
326 int spandisks = query.
value(2).toInt();
327 QString GameName = query.
value(3).toString();
335 int pos = RomName.lastIndexOf(
".");
338 extlength = RomName.length() - pos;
341 basename = RomName.mid(pos,1);
344 if (basename.contains(multiDiskRGXP))
346 pos = (RomName.length() - extlength) - 1;
347 basename = RomName.left(pos);
349 if (basename.right(1) ==
".")
350 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 : std::as_const(
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 : std::as_const(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"));
634 QDir RomDir(directory);
637 if (!RomDir.isReadable())
640 RomDir.setSorting( QDir:: DirsFirst | QDir::Name );
641 RomDir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
642 QFileInfoList List = RomDir.entryInfoList();
643 for (
const auto & Info : std::as_const(List))
645 QString RomName = Info.fileName();
646 QString GameName = Info.completeBaseName();
656 QRegularExpression r {
657 "^" + Info.suffix() +
"$",
658 QRegularExpression::CaseInsensitiveOption };
661 std::copy_if(exts.cbegin(), exts.cend(), std::back_inserter(result),
662 [&r](
const QString& extension){ return extension.contains(r); } );
663 if (result.isEmpty())
668 GameName, Info.absoluteDir().path());
670 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Found ROM : (%1) - %2")
673 *filecount = *filecount + 1;
691 LOG(VB_GENERAL, LOG_ERR,
LOC +
692 QString(
"ROM Path does not exist: %1")
707 QString message = tr(
"Scanning for %1 games...")
712 if (busyDialog->Create())
713 popupStack->
AddScreen(busyDialog,
false);
717 busyDialog =
nullptr;
730 LOG(VB_GENERAL, LOG_INFO,
LOC +
731 QString(
"PC Game %1").arg(handler->
SystemName()));
735 QString message = tr(
"Scanning for %1 games...")
773 QStringList updatelist;
775 for (
auto *handler : std::as_const(*
handlers))
780 handler->processGames(handler);
782 if (handler->needRebuild())
783 updatelist.append(handler->GameType());
787 if (!updatelist.isEmpty())
796 for (
auto *handler : std::as_const(*
handlers))
800 if (rominfo->
System() == handler->SystemName())
810 if (systemname.isEmpty())
813 for (
auto *handler : std::as_const(*
handlers))
817 if (handler->SystemName() == systemname)
829 if (!systemname.isEmpty())
836 if (handler ==
nullptr)
849 QString arg =
"\"" + romdata->
Rompath() +
850 "/" + romdata->
Romname() +
"\"";
855 if (exec.contains(
"%s") || handler->
SpanDisks())
857 exec = exec.replace(
"%s",arg);
861 static const QRegularExpression rxp {
"%d[0-4]" };
863 if (exec.contains(rxp))
871 std::array<QString,7> diskid {
"%d0",
"%d1",
"%d2",
"%d3",
"%d4",
"%d5",
"%d6" };
873 for (
int disk = 1; disk <= romdata->
DiskCount(); disk++)
875 rom = QString(
"\"%1/%2%3.%4\"")
876 .arg(romdata->
Rompath(), basename,
877 QString::number(disk), extension);
878 exec = exec.replace(diskid[disk],rom);
882 exec = exec.replace(
"%d1",arg);
889 exec = exec +
" \"" +
901 LOG(VB_GENERAL, LOG_ERR,
LOC +
902 QString(
"Failed to change to specified Working Directory: %1")
906 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Launching Game : %1 : %2")
912 QStringList cmdlist = exec.split(
";");
913 if (cmdlist.count() > 0)
915 for (
const auto & cmd : std::as_const(cmdlist))
917 LOG(VB_GENERAL, LOG_INFO,
LOC +
918 QString(
"Executing : %1").arg(cmd));
924 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Executing : %1").arg(exec));
950 QString resultid = dce->GetId();
953 if (resultid ==
"removalPopup")
955 int buttonNum = dce->GetResult();
973 else if (resultid ==
"clearAllPopup")
975 int buttonNum = dce->GetResult();
991 if (!query.
exec(
"DELETE FROM gamemetadata;"))
993 "delete gamemetadata", query);