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