MythTV  master
rom_metadata.cpp
Go to the documentation of this file.
1 // C++
2 #include <array>
3 
4 // Qt
5 #include <QFile>
6 
7 // MythTV
8 #include <libmyth/mythcontext.h>
9 
10 // MythGame
11 #include "rom_metadata.h"
12 
13 #include "zlib.h"
14 #undef Z_NULL
15 #define Z_NULL nullptr
16 #include "zip.h"
17 
18 static int calcOffset(const QString& GameType, uint32_t filesize) {
19  int result = 0;
20 
21  if (GameType == "NES")
22  {
23  result = 16;
24  }
25  else if (GameType == "SNES")
26  {
27  uint32_t rom_size = (filesize / 0x2000) * 0x2000;
28 
29  if (rom_size < filesize)
30  result = filesize - rom_size;
31  }
32  else if (GameType == "PCE")
33  {
34  if (filesize & 0x0FFF)
35  result = filesize & 0x0FFF;
36 
37  }
38 
39  return result;
40 }
41 
42 static QString crcStr(uint32_t crc)
43 {
44  QString tmpcrc("");
45 
46  tmpcrc = QString("%1").arg( crc, 0, 16 );
47  if (tmpcrc == "0")
48  tmpcrc = "";
49  else
50  tmpcrc = tmpcrc.rightJustified(8, '0');
51 
52  return tmpcrc;
53 }
54 
55 // NOLINTNEXTLINE(readability-uppercase-literal-suffix)
56 static constexpr uint64_t STATS_REQUIRED {ZIP_STAT_NAME|ZIP_STAT_INDEX|ZIP_STAT_SIZE};
57 
58 // Return the crc32 info for this rom. (ripped mostly from the old neshandler.cpp source)
59 QString crcinfo(const QString& romname, const QString& GameType, QString *key, RomDBMap *romDB)
60 {
61  // Get CRC of file
62  std::array<char,32768> block {};
63  uint32_t crc = crc32(0, nullptr, 0);
64  QString crcRes;
65 
66  int blocksize = 8192;
67 #if 0
68  LOG(VB_GENERAL, LOG_DEBUG,
69  QString("crcinfo : %1 : %2 :").arg(romname).arg(GameType));
70 #endif
71 
72  int err { ZIP_ER_OK };
73  zip_t *zf = zip_open(qPrintable(romname), 0, &err);
74  if (zf != nullptr)
75  {
76  zip_int64_t numEntries = zip_get_num_entries(zf, 0);
77  for (int index = 0; index < numEntries; index++)
78  {
79  zip_file_t *infile = zip_fopen_index(zf, index, 0);
80  if (infile)
81  {
82  zip_stat_t stats;
83  zip_stat_init(&stats);
84  zip_stat_index(zf, index, 0, &stats);
85  if ((stats.valid & STATS_REQUIRED) != STATS_REQUIRED)
86  continue;
87 
88  int offset = calcOffset(GameType, stats.size);
89 
90  if (offset > 0)
91  zip_fread(infile, block.data(), offset);
92 
93  // Get CRC of rom data
94  int count = 0;
95  while ((count = zip_fread(infile, block.data(), blocksize)) > 0)
96  {
97  crc = crc32(crc, (Bytef *)block.data(), (uInt)count);
98  }
99  crcRes = crcStr(crc);
100  *key = QString("%1:%2").arg(crcRes, stats.name);
101 
102  if (romDB->contains(*key))
103  {
104  zip_fclose(infile);
105  break;
106  }
107  zip_fclose(infile);
108  }
109  }
110  zip_close(zf);
111  }
112  else
113  {
114  QFile f(romname);
115 
116  if (f.open(QIODevice::ReadOnly))
117  {
118  int offset = calcOffset(GameType, f.size());
119 
120  if (offset > 0)
121  f.read(block.data(), offset);
122 
123  // Get CRC of rom data
124  qint64 count = 0;
125  while ((count = f.read(block.data(), blocksize)) > 0)
126  {
127  crc = crc32(crc, (Bytef *)block.data(), (uInt)count);
128  }
129 
130  crcRes = crcStr(crc);
131  *key = QString("%1:").arg(crcRes);
132  f.close();
133  }
134  }
135 
136  return crcRes;
137 }
138 
crcStr
static QString crcStr(uint32_t crc)
Definition: rom_metadata.cpp:42
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
STATS_REQUIRED
static constexpr uint64_t STATS_REQUIRED
Definition: rom_metadata.cpp:56
calcOffset
static int calcOffset(const QString &GameType, uint32_t filesize)
Definition: rom_metadata.cpp:18
crcinfo
QString crcinfo(const QString &romname, const QString &GameType, QString *key, RomDBMap *romDB)
Definition: rom_metadata.cpp:59
RomDBMap
QMap< QString, RomData > RomDBMap
Definition: rom_metadata.h:49
mythcontext.h
GameType
Definition: gamesettings.cpp:246
crc32
static uint32_t crc32(const unsigned char *data, int len)
Definition: dsmcc.cpp:616
rom_metadata.h
MythUIComboBoxSetting::size
virtual int size(void) const
Definition: standardsettings.cpp:621